`
cloudtech
  • 浏览: 4611523 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

一个OpenGL后台渲染的架构

 
阅读更多
/**
* a dummy window is invisible with message loop
*/
// 内存泄漏检测
// 在需要检测的地方放置语句:
// _CrtDumpMemoryLeaks();
// 以下3句的次序不能改变
#define _CRTDBG_MAP_ALLOC
#include<stdlib.h>
#include<crtdbg.h>

#include <windows.h>
#include <process.h>

#include <stdio.h>
#include <assert.h>

#define DUMMY_WND_STYLE (WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_POPUP)

#define DUMMY_WND_WIDTH 500
#define DUMMY_WND_HEIGHT 400

static int loopFlag = 1;

// First of all we should have a backend buffer (a block of pixels array).
// We must ensure this backend is thread safe since we want to fill the OGL
// frame data into it and then flush it onto the target device.
// Typically this backend buffer is a DIBSection with a valid HDC that is
// compatiable with target.
typedef struct
{
CRITICAL_SECTION __lock;
int updateId;
HWND dummyWnd;

/// DIBSection bmp;
} BackendBuffer, *BACKEND;

BACKEND BackendBufferCreate (HWND dummyWnd)
{
BACKEND backend = (BACKEND) malloc(sizeof(BackendBuffer));
InitializeCriticalSection(&backend->__lock);
backend->updateId = 0;
backend->dummyWnd = dummyWnd;

printf("BackendBufferCreate(): Prepare OGL context\n");

// Create DIBSection for backend from dummyWnd PixlFormat
// ...
printf("BackendBufferCreate(): Create DIBSection for backend\n");

return backend;
}

void BackendBufferDelete (BACKEND backend)
{
DeleteCriticalSection(&backend->__lock);

// Free DIBSection for backend...

free(backend);
}

typedef void (* pfcb_oglRenderFunc) (void *backend);

static void oglRenderBackend (void *param)
{
BACKEND backend = (BACKEND) param;
printf("ogl Render on backend: %d\n", backend->updateId);

// Fill in DIBSection of backend...
// ...readPixels(...);

// modify updateId that means the backend has been changed
backend->updateId++;
if (backend->updateId > 100000000) {
backend->updateId = 0;
}
}

BOOL BackendBufferUpdate (BACKEND backend, pfcb_oglRenderFunc oglRenderFunc)
{
if (TryEnterCriticalSection(&backend->__lock)) {
oglRenderFunc(backend);

LeaveCriticalSection(&backend->__lock);
// We notice caller update successfully
return TRUE;
} else {
// Something error
return FALSE;
}
}

typedef struct
{
int updateId;
BACKEND backend;

// target device handle: can be HWND or FILE, ...
HWND targetWnd;
} TargetSurface, *TARGET;

TARGET TargetSurfaceCreate (HWND targetWnd, HWND hwndBackend)
{
TARGET tgt = (TargetSurface*) malloc(sizeof(TargetSurface));
tgt->updateId = -1;
tgt->backend = BackendBufferCreate(hwndBackend);
tgt->targetWnd = targetWnd;
return tgt;
}

void TargetSurfaceDelete (TARGET tgt)
{
BackendBufferDelete(tgt->backend);
free(tgt);
}

// Below function should be called in OnDraw() or onRefreshEvent()
//
void TargetSurfaceUpdate (TARGET tgt)
{
if (tgt->updateId != tgt->backend->updateId) {
// Only update target when updateId not equal
if (TryEnterCriticalSection(&tgt->backend->__lock)) {
// Do update target device job here...BitBlt(...);
Sleep(20); // We suppose it will cost me 20 msec to update device
printf("TargetSurface has been updated:%d\n", tgt->updateId);

// Set update target ok
tgt->updateId = tgt->backend->updateId;
LeaveCriticalSection(&tgt->backend->__lock);
}
}
}

static void Fire_OnDraw(TARGET target)
{
TargetSurfaceUpdate(target);
}

static void renderOGLScene (TARGET target)
{
// target can be convey to OGL render engine
// OGL render engine can change
printf("renderOGLScene use target... \n");

if (BackendBufferUpdate(target->backend, oglRenderBackend)) {
// Fire_OnDraw will trigger systen,
// and system will call TargetSurfaceUpdate by sequence
Fire_OnDraw(target);
}

// We suppose it takes 10 ms to render OGL
Sleep(10);
}

static void renderThreadFunc (void *param)
{
MSG msg;

TARGET target = (TARGET) param;

while (loopFlag) {
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
printf("renderThreadFunc recv a WM_QUIT message\n");
break ;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
renderOGLScene(target);
}
}

printf("renderThreadFunc quit\n");
}

HWND createDummyWindow (int width, int height)
{
HWND hwndDummy = CreateWindowA("STATIC",
"DummyWindowForOpenGLOffScreen",
DUMMY_WND_STYLE,
0, 0, width, height,
0, 0, 0, 0);
return hwndDummy;
}

UINT createRenderThread (void *param)
{
UINT threadId = 0;
HANDLE threadHandle = (HANDLE)_beginthreadex(0, 0,
(unsigned (__stdcall *)(void *))renderThreadFunc, param, 0, &threadId);
assert(threadHandle);
CloseHandle(threadHandle);
return threadId;
}

int main ()
{
BOOL ret;
HWND hwndDummy;
UINT threadId;

TARGET target;

hwndDummy = createDummyWindow(DUMMY_WND_WIDTH, DUMMY_WND_HEIGHT);
assert(hwndDummy);
printf("Create dummy window for OGL\n");

printf("Then create a target for drawing\n");
target = TargetSurfaceCreate((HWND)123, hwndDummy);
assert(target);

threadId = createRenderThread(target);
printf("Create OGL render thread\n");

// analogy to do somthing
Sleep(10000);

printf("Notify RenderThread to quit\n");
ret = PostThreadMessage(threadId, WM_QUIT, 0, 0);
assert(ret);

// analogy to do somthing
Sleep(10000);

printf("Main app shutdown\n");
TargetSurfaceDelete(target);
_CrtDumpMemoryLeaks();
exit(0);
}

分享到:
评论

相关推荐

    qt opengl 渲染 yv12

    qt opengl 渲染 显示 yv12 qt opengl 渲染 显示 yv12 qt opengl 渲染 显示 yv12 qt opengl 渲染 显示 yv12 qt opengl 渲染 显示 yv12

    Unity3D调用Native OpenGL渲染方式

    Unity3D调用Native OpenGL,Unity3D支持调用C++工程的OpenGL渲染,使用RenderingPlugin DLL方式。

    OpenGL4.0+vs2019渲染一个模型

    本教程将介绍如何使用GLSL在OpenGL 4.0中渲染3D模型。...现在已经涵盖了基础知识,我们将继续渲染一个更复杂的对象。在这种情况下,对象将是一个立方体。在介绍如何渲染更复杂的模型之前,我们将首先讨论模型格式。

    VC++ 点云数据显示,OPENGL图像渲染

    VC++ 点云数据显示,OPENGL图像渲染~可以直接运行

    一个简单的OpenGL多线程渲染模型

    用多线程实现OpenGL渲染, 子线程负责渲染, 主线程负责干其他事情.

    qt opengl(after ver2.1) 渲染 nv12

    qt opengl(after ver2.1) 渲染 nv12 qt opengl(after ver2.1) 渲染 nv12 qt opengl(after ver2.1) 渲染 nv12

    QML和OpenGL混合渲染(演示程序)

    此资源是演示程序,包含了Windows、Linux、MacOS X以及Android的演示程序,大家可以免...接下来的这篇文章讲的是我们使用QML,借助Qt库和OpenGL,实现了使用着色器定义OpenGL的渲染方式,为大家呈现混合渲染的效果。

    基于OpenGL的海底地形三维渲染方法

    本文分析比较了颜色模型与光照模型,提出基于HSL颜色模型的海底地形多色渐变渲染与配色方法,基于OpenGL进行了真实感光照模型的设置,并分析了影响光照效果的相关因素,最终实现了以海底数字高程模型为数据基础并叠加...

    Android Native层使用opengl es渲染yuv420

    Android Native层使用opengl es渲染yuv420,通过egl绑定android的surface,直接在native层进行渲染 具体使用见http://blog.csdn.net/lidec/article/details/73732369#comments

    opengles渲染NV21

    利用OpenglEs实现NV21的渲染,内部使用读文件的方式进行原始YUV数据的获取,通过实现GLSufraceView与Renderer实现渲染

    c#下opengl渲染

    c#下通过opentk库进行简单的opengl渲染

    opengl渲染到纹理技术

    opengl渲染到纹理技术,RendertoaTexture很好的例子

    OpenGL渲染管线

    OpenGL渲染管线 绝大数OpenGL实现都有相似的操作顺序,一系列相关的...图1-2显示了这些顺序,虽然并没有严格规定OpenGL必须采用这样的实现,但它提供了一个可靠的指南,可以预测OpenGL将以什么样的顺序来执行这些操作。

    Android opengl渲染yuv420例子

    Android下使用OpenGL渲染yuv420p图像并显示。例子中提供了两种类型,一种使用GLSurfaceView在onDrawframe中调用native方法绘制,另外一种使用EGL,直接在native层完成渲染和显示功能。

    VC 使用OpenGL技术渲染三维模型的示例.rar

    VC 使用OpenGL技术渲染三维模型的示例,图形渲染实例,基于OpenGL技术实现,不是太复杂的实例,欢迎大家下载体验。

    【OpenGL ES】离屏渲染

    本资源使用 OpenGL ES 的 FBO 技术实现离屏渲染,使用 ImageView 显示离屏渲染后的图片(将原图片变灰)。博客见:https://zhyan8.blog.csdn.net/article/details/123749012

    Android代码-一个使用openGL渲染的炫丽Android动画库 MagicSurfaceView

    一个MagicSurfaceView只能同时渲染一个MagicScene 一个MagicScene可以包含多个MagicSurface 一个MagicSurface可以对应一个View或者Bitmap对象 场景创建及渲染 // 创建一个MagicSurface对象 MagicSurface surface = ...

    用OpenGL渲染的3D开源引擎

    一款3dFPS游戏引擎,利用OPENGL渲染。可以供初学者学习。

    现代OpenGL+Qt:GLSL双面渲染

    在Qt框架下,用现代OpenGL实现的双面渲染,渲染对象是常见的茶壶模型,详见CSDN博客现代OpenGL+Qt学习笔记之八:GLSL双面渲染。

    OpenGL实现离屏渲染(Offscreen Render),

    这是一个初级的OpenGL程序Demo,实现了Offscreen Render,在VS下可以直接运行,拖动鼠标右键可以实现内正方体的转动,拖动鼠标左键可以实现外正方体的转动;适合初学OpenGL

Global site tag (gtag.js) - Google Analytics