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

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

gpu: rename FrameBuffer to Framebuffer.

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