⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 display_window_opengl.cpp

📁 这是一款2d游戏引擎
💻 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 + -