source: trunk/src/video.cpp @ 2761

Last change on this file since 2761 was 2761, checked in by sam, 8 years ago

gpu: implement face culling mode in render contexts.

  • Property svn:keywords set to Id
File size: 8.2 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://www.wtfpl.net/ for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#if defined _XBOX
16#   include <xtl.h>
17#   undef near /* Fuck Microsoft */
18#   undef far /* Fuck Microsoft again */
19#elif defined _WIN32
20#   if defined USE_D3D9
21#      include <d3d9.h>
22#   endif
23#   define WIN32_LEAN_AND_MEAN
24#   include <windows.h>
25#   undef near /* Fuck Microsoft */
26#   undef far /* Fuck Microsoft again */
27#endif
28
29#include "core.h"
30#include "lolgl.h"
31
32using namespace std;
33
34/* FIXME: g_d3ddevice should never be exported */
35#if defined USE_D3D9
36IDirect3DDevice9 *g_d3ddevice;
37extern HWND g_hwnd;
38#elif defined _XBOX
39D3DDevice *g_d3ddevice;
40HWND g_hwnd = 0;
41#endif
42
43namespace lol
44{
45
46class VideoData
47{
48    friend class Video;
49
50private:
51    static ivec2 saved_viewport;
52    static DebugRenderMode render_mode;
53#if defined USE_D3D9 || defined _XBOX
54#   if defined USE_D3D9
55    static IDirect3D9 *d3d_ctx;
56    static IDirect3DDevice9 *d3d_dev;
57#   elif defined _XBOX
58    static Direct3D *d3d_ctx;
59    static D3DDevice *d3d_dev;
60#   endif
61#endif
62};
63
64ivec2 VideoData::saved_viewport(0, 0);
65DebugRenderMode VideoData::render_mode = DebugRenderMode::Default;
66
67#if defined USE_D3D9 || defined _XBOX
68#   if defined USE_D3D9
69IDirect3D9 *VideoData::d3d_ctx;
70IDirect3DDevice9 *VideoData::d3d_dev;
71#   elif defined _XBOX
72Direct3D *VideoData::d3d_ctx;
73D3DDevice *VideoData::d3d_dev;
74#   endif
75#endif
76
77/*
78 * Public Video class
79 */
80
81void Video::Setup(ivec2 size)
82{
83#if defined USE_D3D9 || defined _XBOX
84    VideoData::d3d_ctx = Direct3DCreate9(D3D_SDK_VERSION);
85    if (!VideoData::d3d_ctx)
86    {
87        Log::Error("cannot initialise D3D\n");
88        exit(EXIT_FAILURE);
89    }
90
91    /* Choose best viewport size */
92#   if defined _XBOX
93    XVIDEO_MODE VideoMode;
94    XGetVideoMode(&VideoMode);
95    size = lol::min(size, ivec2(VideoMode.dwDisplayWidth,
96                                VideoMode.dwDisplayHeight);
97#   endif
98    VideoData::saved_viewport = size;
99
100    D3DPRESENT_PARAMETERS d3dpp;
101    memset(&d3dpp, 0, sizeof(d3dpp));
102    d3dpp.BackBufferWidth = size.x;
103    d3dpp.BackBufferHeight = size.y;
104    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
105    d3dpp.BackBufferCount = 1;
106    d3dpp.hDeviceWindow = g_hwnd;
107#   if defined USE_SDL
108    d3dpp.Windowed = TRUE;
109#   endif
110    d3dpp.EnableAutoDepthStencil = TRUE;
111    d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
112    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
113    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
114
115    HRESULT hr = VideoData::d3d_ctx->CreateDevice(0, D3DDEVTYPE_HAL, g_hwnd,
116                                                  D3DCREATE_HARDWARE_VERTEXPROCESSING,
117                                                  &d3dpp, &VideoData::d3d_dev);
118    if (FAILED(hr))
119    {
120        Log::Error("cannot create D3D device\n");
121        exit(EXIT_FAILURE);
122    }
123
124    g_d3ddevice = VideoData::d3d_dev;
125
126    g_renderer = new Renderer();
127#else
128    /* Initialise OpenGL */
129    g_renderer = new Renderer();
130
131    glViewport(0, 0, size.x, size.y);
132    VideoData::saved_viewport = size;
133#endif
134
135    /* Initialise reasonable scene default properties */
136    SetDebugRenderMode(DebugRenderMode::Default);
137}
138
139void Video::SetCustomSize(ivec2 size)
140{
141    ivec4 current_size(0);
142#if defined USE_D3D9 || defined _XBOX
143#   define STR0(x) #x
144#   define STR(x) STR0(x)
145#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Video::SetSize() not implemented")
146#elif defined __CELLOS_LV2__
147    // FIXME: use psglCreateDeviceAuto && psglGetDeviceDimensions
148#else
149    glGetIntegerv(GL_VIEWPORT, (GLint*)&current_size);
150    if (current_size.zw != size)
151        glViewport(0, 0, size.x, size.y);
152#endif
153}
154
155void Video::RestoreSize()
156{
157    ivec4 current_size(0);
158#if defined USE_D3D9 || defined _XBOX
159#   define STR0(x) #x
160#   define STR(x) STR0(x)
161#   pragma message(__FILE__ "(" STR(__LINE__) "): warning: Video::SetSize() not implemented")
162#elif defined __CELLOS_LV2__
163    // FIXME: use psglCreateDeviceAuto && psglGetDeviceDimensions
164#else
165    glGetIntegerv(GL_VIEWPORT, (GLint*)&current_size);
166    if (current_size.zw != VideoData::saved_viewport)
167        glViewport(0, 0, VideoData::saved_viewport.x, VideoData::saved_viewport.y);
168#endif
169}
170
171void Video::SetDebugRenderMode(DebugRenderMode d)
172{
173    switch(d)
174    {
175        //All these modes are handled in the shaders.
176        case DebugRenderMode::Default:
177        case DebugRenderMode::Lighting:
178        case DebugRenderMode::Normal:
179        case DebugRenderMode::UV:
180        {
181#if defined USE_D3D9 || defined _XBOX
182#elif defined HAVE_GLES_2X
183//            glEnable(GL_CULL_FACE);
184#else
185//            if (VideoData::render_mode == d && glIsEnabled(GL_CULL_FACE) == GL_TRUE)
186//                SetFaceCulling(false);
187//            else
188//                SetFaceCulling(true);
189            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
190#endif
191            break;
192        }
193        case DebugRenderMode::Wireframe:
194        {
195            if (VideoData::render_mode == d)
196            {
197#if defined USE_D3D9 || defined _XBOX
198#else
199//                SetFaceCulling(!VideoData::face_culling);
200#endif
201            }
202            else
203            {
204#if defined USE_D3D9 || defined _XBOX
205#else
206//                SetFaceCulling(false);
207#endif
208            }
209#if defined USE_D3D9 || defined _XBOX
210#elif defined HAVE_GLES_2X
211#else
212            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
213#endif
214            break;
215        }
216        default:
217            return; /* Unknown render mode */
218    }
219    VideoData::render_mode = d;
220}
221
222DebugRenderMode Video::GetDebugRenderMode()
223{
224    return VideoData::render_mode;
225}
226
227void Video::Clear(ClearMask m)
228{
229#if defined USE_D3D9 || defined _XBOX
230    int mask = 0;
231    if (m & ClearMask::Color)
232        mask |= D3DCLEAR_TARGET;
233    if (m & ClearMask::Depth)
234        mask |= D3DCLEAR_ZBUFFER;
235    if (m & ClearMask::Stencil)
236        mask |= D3DCLEAR_STENCIL;
237
238    vec4 tmp = 255.999f * g_renderer->GetClearColor();
239    D3DCOLOR clear_color = D3DCOLOR_XRGB((int)tmp.r, (int)tmp.g, (int)tmp.b);
240
241    if (FAILED(VideoData::d3d_dev->Clear(0, nullptr, mask,
242                                         clear_color,
243                                         g_renderer->GetClearDepth(), 0)))
244        Abort();
245#else
246    /* FIXME: is this necessary here? */
247    ivec2 size = GetSize();
248    glViewport(0, 0, size.x, size.y);
249
250    GLbitfield mask = 0;
251    if (m & ClearMask::Color)
252        mask |= GL_COLOR_BUFFER_BIT;
253    if (m & ClearMask::Depth)
254        mask |= GL_DEPTH_BUFFER_BIT;
255    if (m & ClearMask::Stencil)
256        mask |= GL_STENCIL_BUFFER_BIT;
257    glClear(mask);
258#endif
259}
260
261void Video::Destroy()
262{
263    delete g_renderer;
264    g_renderer = nullptr;
265}
266
267void Video::Capture(uint32_t *buffer)
268{
269#if defined USE_D3D9 || defined _XBOX
270    /* TODO */
271#else
272    GLint v[4];
273#   if defined __CELLOS_LV2__
274    // FIXME: use psglCreateDeviceAuto && psglGetDeviceDimensions
275    v[2] = 1920;
276    v[3] = 1080;
277#   else
278    glGetIntegerv(GL_VIEWPORT, v);
279#   endif
280    int width = v[2], height = v[3];
281
282#   if defined HAVE_GL_2X
283    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
284#   endif
285    glPixelStorei(GL_PACK_ALIGNMENT, 1);
286
287#   if defined GL_BGRA
288    glReadPixels(0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, buffer);
289#   else
290    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
291#   endif
292
293    for (int j = 0; j < height / 2; j++)
294        for (int i = 0; i < width; i++)
295        {
296            uint32_t tmp = buffer[j * width + i];
297            buffer[j * width + i] = buffer[(height - j - 1) * width + i];
298            buffer[(height - j - 1) * width + i] = tmp;
299        }
300#endif
301}
302
303ivec2 Video::GetSize()
304{
305#if defined USE_D3D9 || defined _XBOX
306    return VideoData::saved_viewport;
307#elif 1
308    /* GetSize() is called too often on the game thread; we cannot rely on
309     * the GL context at this point */
310    return VideoData::saved_viewport;
311#elif defined __CELLOS_LV2__
312    // FIXME: use psglCreateDeviceAuto && psglGetDeviceDimensions
313#else
314    GLint v[4];
315    glGetIntegerv(GL_VIEWPORT, v);
316    return ivec2(v[2], v[3]);
317#endif
318}
319
320} /* namespace lol */
321
Note: See TracBrowser for help on using the repository browser.