📄 display_window_opengl.cpp
字号:
/* $Id: display_window_opengl.cpp,v 1.33 2003/12/29 14:52:59 sphair Exp $
**
** ClanLib Game SDK
** Copyright (C) 2003 The ClanLib Team
** For a total list of contributers see the file CREDITS.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Display/display_precomp.h"
#include "display_window_opengl.h"
#include "GL/graphic_context_opengl.h"
#include "GL/pixel_buffer_opengl_frame.h"
#include "GL/gl_state_checker.h"
#include "API/Display/display_window_description.h"
#include "API/Core/System/error.h"
#include "API/GL/opengl_state.h"
#include "API/GL/opengl_wrap.h"
#ifndef AC_SRC_ALPHA
#define AC_SRC_ALPHA 1
#endif
#ifndef ULW_OPAQUE
#define ULW_OPAQUE 0
#endif
#ifndef ULW_COLORKEY
#define ULW_COLORKEY 1
#endif
#ifndef ULW_ALPHA
#define ULW_ALPHA 2
#endif
/////////////////////////////////////////////////////////////////////////////
// Construction:
CL_DisplayWindow_OpenGL::CL_DisplayWindow_OpenGL()
{
layered_dc = 0;
layered_bitmap = 0;
context = 0;
hdc = 0;
gc = CL_GraphicContext(new CL_GraphicContext_OpenGL(this));
buffer_front = CL_PixelBuffer(new CL_PixelBuffer_OpenGL_Frame(CL_FRONT, gc));
buffer_back = CL_PixelBuffer(new CL_PixelBuffer_OpenGL_Frame(CL_BACK, gc));
user32_dll = 0;
}
CL_DisplayWindow_OpenGL::~CL_DisplayWindow_OpenGL()
{
if (layered_bitmap)
{
SelectObject(layered_dc, layered_orig_bitmap);
DeleteObject(layered_bitmap);
}
if (layered_dc) DeleteDC(layered_dc);
if (user32_dll) FreeLibrary(user32_dll);
}
/////////////////////////////////////////////////////////////////////////////
// Attributes:
CL_GraphicContext *CL_DisplayWindow_OpenGL::get_gc()
{
return &gc;
}
CL_PixelBuffer &CL_DisplayWindow_OpenGL::get_buffer(int i)
{
if (i == 0) return buffer_front;
else return buffer_back;
}
const CL_PixelBuffer &CL_DisplayWindow_OpenGL::get_buffer(int i) const
{
if (i == 0) return buffer_front;
else return buffer_back;
}
int CL_DisplayWindow_OpenGL::get_buffer_count() const
{
return 2;
}
HDC CL_DisplayWindow_OpenGL::get_dc()
{
if (layered_dc) return layered_dc;
return hdc;
}
/////////////////////////////////////////////////////////////////////////////
// Operations:
void CL_DisplayWindow_OpenGL::create_window(const CL_DisplayWindowDescription &desc)
{
if (desc.is_fullscreen())
{
set_videomode(desc.get_size().width, desc.get_size().height, desc.get_bpp(), desc.get_refresh_rate());
}
else
{
restore_videomode();
}
CL_DisplayWindow_Win32::create_window(desc);
if (context) return; // OpenGL already setup for this window
// Setup OpenGL:
hdc = GetDC(get_hwnd());
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER /*| // double buffered
PFD_DEPTH_DONTCARE*/, // do you care about a zbuffer?
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
if (desc.is_layered())
{
pfd.cAlphaBits = 8;
pfd.dwFlags |= PFD_DRAW_TO_BITMAP | PFD_DOUBLEBUFFER_DONTCARE;
}
if (desc.is_layered())
{
if (user32_dll == 0)
{
user32_dll = LoadLibrary("user32.dll");
if (user32_dll == 0) throw CL_Error("Unable to load user32.dll!");
ptr_UpdateLayeredWindow = (PtrUpdateLayeredWindow) GetProcAddress(user32_dll, "UpdateLayeredWindow");
if (ptr_UpdateLayeredWindow == 0)
{
FreeLibrary(user32_dll);
user32_dll = 0;
throw CL_Error("Layered windows require Windows 2000 or Windows XP!");
}
}
layered_dc = CreateCompatibleDC(hdc);
cl_assert(layered_dc != 0);
layered_bitmap = CreateCompatibleBitmap(hdc, desc.get_size().width, desc.get_size().height);
cl_assert(layered_bitmap != 0);
layered_orig_bitmap = (HBITMAP) SelectObject(layered_dc, layered_bitmap);
}
int pixelformat = ChoosePixelFormat(get_dc(), &pfd);
SetPixelFormat(get_dc(), pixelformat, &pfd);
context = wglCreateContext(get_dc());
cl_assert(context != NULL);
if (!opengl_contexts.empty()) wglShareLists(opengl_contexts.back(), context);
opengl_contexts.push_back(context);
ShowWindow(get_hwnd(), SW_SHOW);
UpdateWindow(get_hwnd());
}
void CL_DisplayWindow_OpenGL::destroy_window()
{
if (context)
{
wglMakeCurrent(0, 0);
wglDeleteContext(context);
context = 0;
opengl_contexts.remove(context);
}
if (layered_bitmap)
{
SelectObject(layered_dc, layered_orig_bitmap);
DeleteObject(layered_bitmap);
layered_bitmap = 0;
}
if (layered_dc) DeleteDC(layered_dc);
layered_dc = 0;
if (is_fullscreen()) restore_videomode();
CL_DisplayWindow_Win32::destroy_window();
}
bool CL_DisplayWindow_OpenGL::received_event(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
if (context)
{
wglMakeCurrent(0, 0);
wglDeleteContext(context);
context = 0;
opengl_contexts.remove(context);
}
break;
}
return CL_DisplayWindow_Win32::received_event(uMsg, wParam, lParam);
}
void CL_DisplayWindow_OpenGL::flip()
{
CL_GLStateChecker::from_gc(get_gc())->flush();
CL_DisplayWindow_Win32::flip();
BOOL retval = SwapBuffers(get_dc());
repaint_layered();
}
void CL_DisplayWindow_OpenGL::update(const CL_Rect &rect)
{
CL_OpenGLState state(get_gc());
state.set_active();
state.setup_2d();
clReadBuffer(CL_BACK);
if (clGetError() == CL_NO_ERROR) // Check if we got more than 1 buffer.
{
CLfloat raster_pos[4];
clGetFloatv(CL_CURRENT_RASTER_POSITION, raster_pos);
clDrawBuffer(CL_FRONT);
clRasterPos3f((CLfloat) rect.left, (CLfloat) rect.bottom, raster_pos[2]);
clCopyPixels(rect.top, rect.left, rect.get_width(), rect.get_height(), CL_COLOR);
// Return to drawing to the back buffer
clDrawBuffer(CL_BACK);
}
repaint_layered();
}
/////////////////////////////////////////////////////////////////////////////
// Implementation:
void CL_DisplayWindow_OpenGL::repaint_layered()
{
if (layered_dc == 0) return; // Not a layered window.
if (ptr_UpdateLayeredWindow == 0) return; // Not supported on this platform.
POINT layer_src_position;
layer_src_position.x = 0;
layer_src_position.y = 0;
POINT layer_dest_position;
layer_dest_position.x = get_layer_position().left;
layer_dest_position.y = get_layer_position().top;
SIZE layer_size;
layer_size.cx = get_width();
layer_size.cy = get_height();
BLENDFUNCTION blendfunc;
blendfunc.BlendOp = AC_SRC_OVER;
blendfunc.BlendFlags = 0;
blendfunc.SourceConstantAlpha = 255;
blendfunc.AlphaFormat = AC_SRC_ALPHA;
ptr_UpdateLayeredWindow(
get_hwnd(),
hdc,
&layer_dest_position,
&layer_size,
layered_dc,
&layer_src_position,
RGB(0,0,0),
&blendfunc,
ULW_COLORKEY/*ULW_ALPHA*/);
}
std::list<HGLRC> CL_DisplayWindow_OpenGL::opengl_contexts;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -