// // Lol Engine // // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> // This program is free software; you can redistribute it and/or // modify it under the terms of the Do What The Fuck You Want To // Public License, Version 2, as published by Sam Hocevar. See // http://www.wtfpl.net/ for more details. // #if defined HAVE_CONFIG_H # include "config.h" #endif #include "core.h" #include "lolgl.h" #if defined _WIN32 && defined USE_D3D9 # define FAR # define NEAR # include <d3d9.h> #endif using namespace std; #if defined USE_D3D9 extern IDirect3DDevice9 *g_d3ddevice; #elif defined _XBOX extern D3DDevice *g_d3ddevice; #endif namespace lol { // // The FrameBufferData class // ------------------------- // class FrameBufferData { friend class FrameBuffer; ivec2 m_size; #if defined USE_D3D9 IDirect3DTexture9 *m_texture; IDirect3DSurface9 *m_surface, *m_back_surface; #elif defined _XBOX D3DTexture *m_texture; D3DSurface *m_surface, *m_back_surface; #else GLuint m_fbo, m_texture, m_depth; #endif }; // // The FrameBuffer class // ---------------------- // FrameBuffer::FrameBuffer(ivec2 size) : m_data(new FrameBufferData) { m_data->m_size = size; #if defined USE_D3D9 if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_data->m_texture, nullptr))) Abort(); if (FAILED(m_data->m_texture->GetSurfaceLevel(0, &m_data->m_surface))) Abort(); #elif defined _XBOX if (FAILED(g_d3ddevice->CreateTexture(size.x, size.y, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_data->m_texture, nullptr))) Abort(); if (FAILED(g_d3ddevice->CreateRenderTarget(size.x, size.y, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, 0, &m_data->m_surface, nullptr))) Abort(); #else # if GL_VERSION_1_1 GLenum internal_format = GL_RGBA8; GLenum format = GL_BGRA; GLenum depth = GL_DEPTH_COMPONENT; # elif defined __CELLOS_LV2__ /* Supported drawable formats on the PS3: GL_ARGB_SCE, GL_RGB16F_ARB, * GL_RGBA16F_ARB, GL_RGB32F_ARB, GL_RGBA32F_ARB, GL_LUMINANCE32F_ARB. */ GLenum internal_format = GL_ARGB_SCE; GLenum format = GL_RGBA; # else GLenum internal_format = GL_RGBA; GLenum format = GL_RGBA; # endif GLenum wrapmode = GL_REPEAT; GLenum filtering = GL_NEAREST; # if GL_VERSION_1_1 || GL_ES_VERSION_2_0 glGenFramebuffers(1, &m_data->m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_data->m_fbo); # else glGenFramebuffersOES(1, &m_data->m_fbo); glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo); # endif glGenTextures(1, &m_data->m_texture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_data->m_texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (GLenum)wrapmode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (GLenum)wrapmode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLenum)filtering); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLenum)filtering); glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size.x, size.y, 0, format, GL_UNSIGNED_BYTE, nullptr); # if GL_VERSION_1_1 || GL_ES_VERSION_2_0 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_data->m_texture, 0); # else glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_data->m_texture, 0); # endif m_data->m_depth = GL_INVALID_ENUM; # if GL_VERSION_1_1 /* FIXME: not implemented on GL ES, see * http://stackoverflow.com/q/4041682/111461 */ if (depth != GL_INVALID_ENUM) { glGenRenderbuffers(1, &m_data->m_depth); glBindRenderbuffer(GL_RENDERBUFFER, m_data->m_depth); glRenderbufferStorage(GL_RENDERBUFFER, depth, size.x, size.y); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_data->m_depth); } # endif # if GL_VERSION_1_1 || GL_ES_VERSION_2_0 glCheckFramebufferStatus(GL_FRAMEBUFFER); # endif Unbind(); #endif } FrameBuffer::~FrameBuffer() { #if defined USE_D3D9 || defined _XBOX m_data->m_surface->Release(); m_data->m_texture->Release(); #else # if GL_VERSION_1_1 || GL_ES_VERSION_2_0 glDeleteFramebuffers(1, &m_data->m_fbo); # else glDeleteFramebuffersOES(1, &m_data->m_fbo); # endif glDeleteTextures(1, &m_data->m_texture); # if GL_VERSION_1_1 if (m_data->m_depth != GL_INVALID_ENUM) glDeleteRenderbuffers(1, &m_data->m_depth); # endif #endif delete m_data; } ShaderTexture FrameBuffer::GetTexture() const { ShaderTexture ret; #if defined USE_D3D9 || defined _XBOX ret.m_flags = (uint64_t)(uintptr_t)m_data->m_texture; #else ret.m_flags = m_data->m_texture; #endif return ret; } void FrameBuffer::Bind() { #if defined USE_D3D9 || defined _XBOX if (FAILED(g_d3ddevice->GetRenderTarget(0, &m_data->m_back_surface))) Abort(); if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_surface))) Abort(); #else # if GL_VERSION_1_1 || GL_ES_VERSION_2_0 glBindFramebuffer(GL_FRAMEBUFFER, m_data->m_fbo); # else glBindFramebufferOES(GL_FRAMEBUFFER_OES, m_data->m_fbo); # endif #endif } void FrameBuffer::Unbind() { #if defined USE_D3D9 if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface))) Abort(); m_data->m_back_surface->Release(); #elif defined _XBOX if (FAILED(g_d3ddevice->Resolve(D3DRESOLVE_RENDERTARGET0, nullptr, m_data->m_texture, nullptr, 0, 0, nullptr, 0, 0, nullptr))) Abort(); if (FAILED(g_d3ddevice->SetRenderTarget(0, m_data->m_back_surface))) Abort(); m_data->m_back_surface->Release(); #else # if GL_VERSION_1_1 || GL_ES_VERSION_2_0 glBindFramebuffer(GL_FRAMEBUFFER, 0); # else glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); # endif #endif } } /* namespace lol */