source: trunk/src/gpu/framebuffer.cpp @ 2596

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

build: various compilation fixes.

  • Property svn:keywords set to Id
File size: 12.1 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#include "core.h"
16#include "lolgl.h"
17
18#if defined _WIN32 && defined USE_D3D9
19#   define FAR
20#   define NEAR
21#   include <d3d9.h>
22#endif
23
24using namespace std;
25
26#if defined USE_D3D9
27extern IDirect3DDevice9 *g_d3ddevice;
28#elif defined _XBOX
29extern D3DDevice *g_d3ddevice;
30#endif
31
32namespace lol
33{
34
35//
36// The FramebufferData class
37// -------------------------
38//
39
40class FramebufferData
41{
42    friend class Framebuffer;
43
44    ivec2 m_size;
45
46#if defined USE_D3D9
47    IDirect3DTexture9 *m_texture;
48    IDirect3DSurface9 *m_surface, *m_back_surface;
49#elif defined _XBOX
50    D3DTexture *m_texture;
51    D3DSurface *m_surface, *m_back_surface;
52#else
53    GLuint m_fbo, m_texture, m_depth;
54#endif
55};
56
57//
58// The FramebufferFormat struct
59// ----------------------
60//
61
62uint32_t FramebufferFormat::GetFormat()
63{
64    switch (m_format)
65    {
66#if defined USE_D3D9 || defined _XBOX
67        case R_16_F:        return D3DFMT_R16F;
68        case R_32_F:        return D3DFMT_R32F;
69        case RG_16:
70        case RG_16_I:
71        case RG_16_UI:      return D3DFMT_G16R16;
72        case RG_16_F:       return D3DFMT_G16R16F;
73        case RG_32_F:       return D3DFMT_G32R32F;
74        case RGB_8:
75        case RGB_8_I:
76        case RGB_8_UI:      return D3DFMT_R8G8B8;
77        case RGBA_8:
78        case RGBA_8_I:
79        case RGBA_8_UI:     return D3DFMT_A8R8G8B8;
80        case RGBA_16:
81        case RGBA_16_I:
82        case RGBA_16_UI:    return D3DFMT_A16B16G16R16;
83        case RGBA_16_F:     return D3DFMT_A16B16G16R16F;
84        case RGBA_32_F:     return D3DFMT_A32B32G32R32F;
85
86        default:            ASSERT(false, "not supported by DirectX");
87                            return 0;
88#elif defined __CELLOS_LV2__
89    /* Supported drawable formats on the PS3: GL_ARGB_SCE, GL_RGB16F_ARB,
90     * GL_RGBA16F_ARB, GL_RGB32F_ARB, GL_RGBA32F_ARB, GL_LUMINANCE32F_ARB. */
91        case RGB_16_F:      return GL_RGB16F_ARB;
92        case RGB_32_F:      return GL_RGB32F_ARB;
93        case RGBA_8:        return GL_ARGB_SCE;
94        case RGBA_16_F:     return GL_RGBA16F_ARB;
95        case RGBA_32_F:     return GL_RGBA32F_ARB;
96
97        default:            ASSERT(false, "not supported by the PS3");
98                            return 0;
99#elif defined HAVE_GLES_2X
100        /* FIXME: not implemented at all */
101
102        default:            ASSERT(false, "not implemented");
103                            return 0;
104#else
105        case R_8:           return GL_R8;
106        case R_8_I:         return GL_R8I;
107        case R_8_UI:        return GL_R8UI;
108
109        case R_16:          return GL_R16;
110        case R_16_I:        return GL_R16I;
111        case R_16_UI:       return GL_R16UI;
112        case R_16_F:        return GL_R16F;
113
114        case R_32_I:        return GL_R32I;
115        case R_32_UI:       return GL_R32UI;
116        case R_32_F:        return GL_R32F;
117
118        case RG_8:          return GL_RG8;
119        case RG_8_I:        return GL_RG8I;
120        case RG_8_UI:       return GL_RG8UI;
121
122        case RG_16:         return GL_RG16;
123        case RG_16_I:       return GL_RG16I;
124        case RG_16_UI:      return GL_RG16UI;
125        case RG_16_F:       return GL_RG16F;
126
127        case RG_32_I:       return GL_RG32I;
128        case RG_32_UI:      return GL_RG32UI;
129        case RG_32_F:       return GL_RG32F;
130
131        case RGB_8:         return GL_RGB8;
132        case RGB_8_I:       return GL_RGB8I;
133        case RGB_8_UI:      return GL_RGB8UI;
134
135        case RGB_16:        return GL_RGB16;
136        case RGB_16_I:      return GL_RGB16I;
137        case RGB_16_UI:     return GL_RGB16UI;
138        case RGB_16_F:      return GL_RGB16F;
139
140        case RGB_32_I:      return GL_RGB32I;
141        case RGB_32_UI:     return GL_RGB32UI;
142        case RGB_32_F:      return GL_RGB32F;
143
144        case RGBA_8:        return GL_RGBA8;
145        case RGBA_8_I:      return GL_RGBA8I;
146        case RGBA_8_UI:     return GL_RGBA8UI;
147
148        case RGBA_16:       return GL_RGBA16;
149        case RGBA_16_I:     return GL_RGBA16I;
150        case RGBA_16_UI:    return GL_RGBA16UI;
151        case RGBA_16_F:     return GL_RGBA16F;
152
153        case RGBA_32_I:     return GL_RGBA32I;
154        case RGBA_32_UI:    return GL_RGBA32UI;
155        case RGBA_32_F:     return GL_RGBA32F;
156
157        default:            ASSERT(false, "not supported by OpenGL");
158                            return 0;
159#endif
160    };
161
162    ASSERT(false, "not implemented");
163    return 0;
164}
165
166uint32_t FramebufferFormat::GetFormatOrder()
167{
168    switch (m_format)
169    {
170#if defined USE_D3D9 || defined _XBOX
171        /* FIXME: not implemented at all */
172        default:            ASSERT(false, "not implemented");
173                            return 0;
174#elif defined __CELLOS_LV2__
175        /* FIXME: not implemented at all */
176        default:            ASSERT(false, "not implemented");
177                            return 0;
178#elif defined HAVE_GLES_2X
179        /* FIXME: not implemented at all */
180        default:            ASSERT(false, "not implemented");
181                            return 0;
182#else
183        case R_8:
184        case R_8_I:
185        case R_8_UI:
186        case R_8_F:
187
188        case R_16:
189        case R_16_I:
190        case R_16_UI:
191        case R_16_F:
192
193        case R_32_I:
194        case R_32:
195        case R_32_UI:
196        case R_32_F:        return GL_RED;
197
198        case RG_8:
199        case RG_8_I:
200        case RG_8_UI:
201        case RG_8_F:
202
203        case RG_16:
204        case RG_16_I:
205        case RG_16_UI:
206        case RG_16_F:
207
208        case RG_32:
209        case RG_32_I:
210        case RG_32_UI:
211        case RG_32_F:       return GL_RG;
212
213        case RGB_8:
214        case RGB_8_I:
215        case RGB_8_UI:
216        case RGB_8_F:
217
218        case RGB_16:
219        case RGB_16_I:
220        case RGB_16_UI:
221        case RGB_16_F:
222
223        case RGB_32:
224        case RGB_32_I:
225        case RGB_32_UI:
226        case RGB_32_F:      return (m_invert_rgb)?(GL_BGR):(GL_RGB);
227
228        case RGBA_8:
229        case RGBA_8_I:
230        case RGBA_8_UI:
231        case RGBA_8_F:
232
233        case RGBA_16:
234        case RGBA_16_I:
235        case RGBA_16_UI:
236        case RGBA_16_F:
237
238        case RGBA_32:
239        case RGBA_32_I:
240        case RGBA_32_UI:
241        case RGBA_32_F:     return (m_invert_rgb)?(GL_BGRA):(GL_RGBA);
242#endif
243    }
244
245    ASSERT(false, "unknown pixel format");
246    return 0;
247}
248
249//
250// The Framebuffer class
251// ----------------------
252//
253
254Framebuffer::Framebuffer(ivec2 size, FramebufferFormat fbo_format)
255  : m_data(new FramebufferData)
256{
257    m_data->m_size = size;
258#if defined USE_D3D9
259    if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1,
260                                          D3DUSAGE_RENDERTARGET,
261                                          fbo_format.GetFormat(), D3DPOOL_DEFAULT,
262                                          &m_data->m_texture, nullptr)))
263        Abort();
264    if (FAILED(m_data->m_texture->GetSurfaceLevel(0, &m_data->m_surface)))
265        Abort();
266#elif defined _XBOX
267    if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1, 0,
268                                          fbo_format.GetFormat(), D3DPOOL_DEFAULT,
269                                          &m_data->m_texture, nullptr)))
270        Abort();
271    if (FAILED(g_d3ddevice->CreateRenderTarget(size.x, size.y,
272                                               fbo_format.GetFormat(),
273                                               D3DMULTISAMPLE_NONE, 0, 0,
274                                               &m_data->m_surface, nullptr)))
275        Abort();
276#else
277#   if GL_VERSION_1_1
278    GLenum internal_format = fbo_format.GetFormat();
279    GLenum format = fbo_format.GetFormatOrder();
280    GLenum depth = GL_DEPTH_COMPONENT;
281#   elif defined __CELLOS_LV2__
282    /* Supported drawable formats on the PS3: GL_ARGB_SCE, GL_RGB16F_ARB,
283     * GL_RGBA16F_ARB, GL_RGB32F_ARB, GL_RGBA32F_ARB, GL_LUMINANCE32F_ARB. */
284    GLenum internal_format = fbo_format.GetFormat();
285    GLenum format = fbo_format.GetFormatOrder();
286#   else
287    GLenum internal_format = fbo_format.GetFormat();
288    GLenum format = fbo_format.GetFormatOrder();
289#   endif
290    GLenum wrapmode = GL_REPEAT;
291    GLenum filtering = GL_NEAREST;
292
293#   if GL_VERSION_1_1 || GL_ES_VERSION_2_0
294    glGenFramebuffers(1, &m_data->m_fbo);
295    glBindFramebuffer(GL_FRAMEBUFFER, m_data->m_fbo);
296#   else
297    glGenFramebuffersOES(1, &m_data->m_fbo);
298    glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo);
299#   endif
300
301    glGenTextures(1, &m_data->m_texture);
302    glActiveTexture(GL_TEXTURE0);
303    glBindTexture(GL_TEXTURE_2D, m_data->m_texture);
304    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLenum)wrapmode);
305    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLenum)wrapmode);
306    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLenum)filtering);
307    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLenum)filtering);
308    glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size.x, size.y, 0,
309                 format, GL_UNSIGNED_BYTE, nullptr);
310
311#   if GL_VERSION_1_1 || GL_ES_VERSION_2_0
312    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
313                           GL_TEXTURE_2D, m_data->m_texture, 0);
314#   else
315    glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_EXT,
316                              GL_TEXTURE_2D, m_data->m_texture, 0);
317#   endif
318
319    m_data->m_depth = GL_INVALID_ENUM;
320#   if GL_VERSION_1_1
321    /* FIXME: not implemented on GL ES, see
322     * http://stackoverflow.com/q/4041682/111461 */
323    if (depth != GL_INVALID_ENUM)
324    {
325        glGenRenderbuffers(1, &m_data->m_depth);
326        glBindRenderbuffer(GL_RENDERBUFFER, m_data->m_depth);
327        glRenderbufferStorage(GL_RENDERBUFFER, depth, size.x, size.y);
328        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
329                                  GL_RENDERBUFFER, m_data->m_depth);
330    }
331#   endif
332
333#   if GL_VERSION_1_1 || GL_ES_VERSION_2_0
334    glCheckFramebufferStatus(GL_FRAMEBUFFER);
335#   endif
336
337    Unbind();
338#endif
339}
340
341Framebuffer::~Framebuffer()
342{
343#if defined USE_D3D9 || defined _XBOX
344    m_data->m_surface->Release();
345    m_data->m_texture->Release();
346#else
347#   if GL_VERSION_1_1 || GL_ES_VERSION_2_0
348    glDeleteFramebuffers(1, &m_data->m_fbo);
349#   else
350    glDeleteFramebuffersOES(1, &m_data->m_fbo);
351#   endif
352    glDeleteTextures(1, &m_data->m_texture);
353#   if GL_VERSION_1_1
354    if (m_data->m_depth != GL_INVALID_ENUM)
355        glDeleteRenderbuffers(1, &m_data->m_depth);
356#   endif
357#endif
358    delete m_data;
359}
360
361ShaderTexture Framebuffer::GetTexture() const
362{
363    ShaderTexture ret;
364#if defined USE_D3D9 || defined _XBOX
365    ret.m_flags = (uint64_t)(uintptr_t)m_data->m_texture;
366#else
367    ret.m_flags = m_data->m_texture;
368#endif
369    return ret;
370}
371
372ivec2 Framebuffer::GetSize() const
373{
374    return m_data->m_size;
375}
376
377void Framebuffer::Bind()
378{
379#if defined USE_D3D9 || defined _XBOX
380    if (FAILED(g_d3ddevice->GetRenderTarget(0, &m_data->m_back_surface)))
381        Abort();
382    if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_surface)))
383        Abort();
384#else
385#   if GL_VERSION_1_1 || GL_ES_VERSION_2_0
386    glBindFramebuffer(GL_FRAMEBUFFER, m_data->m_fbo);
387#   else
388    glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo);
389#   endif
390    //change viewport draw size
391    Video::SetCustomSize(m_data->m_size);
392#endif
393}
394
395void Framebuffer::Unbind()
396{
397#if defined USE_D3D9
398    if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface)))
399        Abort();
400    m_data->m_back_surface->Release();
401#elif defined _XBOX
402    if (FAILED(g_d3ddevice->Resolve(D3DRESOLVE_RENDERTARGET0, nullptr,
403                                    m_data->m_texture, nullptr, 0, 0, nullptr,
404                                    0, 0, nullptr)))
405        Abort();
406    if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface)))
407        Abort();
408    m_data->m_back_surface->Release();
409#else
410    //Restore viewport draw size
411    Video::RestoreSize();
412#   if GL_VERSION_1_1 || GL_ES_VERSION_2_0
413    glBindFramebuffer(GL_FRAMEBUFFER, 0);
414#   else
415    glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
416#   endif
417#endif
418}
419
420} /* namespace lol */
421
Note: See TracBrowser for help on using the repository browser.