OpenGL Renderer:

- Major rewrite of the OpenGL rendering code! Most important changes listed below.
- Encapsulate 3D rendering code in C++ classes.
- Add support for 3.2 Core Profile contexts, while preserving backwards compatibility with legacy contexts.
- Initialize the renderer to choose the best OpenGL entry points available from the driver, automatically falling back to legacy entry points as needed.
- Remove multithreading code. New and previous optimizations have obsoleted the need for it, so remove it to reduce code complexity.
- Obsolete shaders.h and add the shader code directly into the .cpp files. Ports can safely remove the shaders.h file from their project/make files.
This commit is contained in:
rogerman 2013-02-04 22:30:20 +00:00
parent d310766240
commit 5b215efacc
8 changed files with 14748 additions and 3275 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2009 DeSmuME team
Copyright (C) 2008-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -20,20 +20,339 @@
#ifndef OGLRENDER_H
#define OGLRENDER_H
#include <queue>
#include <set>
#include <string>
#include "render3D.h"
#include "types.h"
// Define minimum required OpenGL version for GPU (Legacy Renderer)
#define OGLRENDER_LEGACY_MINIMUM_GPU_VERSION_REQUIRED_MAJOR 1
#define OGLRENDER_LEGACY_MINIMUM_GPU_VERSION_REQUIRED_MINOR 2
#define OGLRENDER_LEGACY_MINIMUM_GPU_VERSION_REQUIRED_REVISION 0
#ifndef OGLRENDER_3_2_H
// Define minimum required OpenGL version for GPU (Modern Renderer)
#define OGLRENDER_MINIMUM_GPU_VERSION_REQUIRED_MAJOR 3
#define OGLRENDER_MINIMUM_GPU_VERSION_REQUIRED_MINOR 0
#define OGLRENDER_MINIMUM_GPU_VERSION_REQUIRED_REVISION 0
#if defined(_WIN32) && !defined(WXPORT)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
#include <GL/glext.h>
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)wglGetProcAddress(#func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#elif defined(__APPLE__)
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
// Ignore dynamic linking on Apple OS
#define OGLEXT(procPtr, func)
#define INITOGLEXT(procPtr, func)
#define EXTERNOGLEXT(procPtr, func)
// We're not exactly committing to OpenGL 3.2 Core Profile just yet, so redefine APPLE
// extensions as a temporary measure.
#if defined(GL_APPLE_vertex_array_object) && !defined(GL_ARB_vertex_array_object)
#define glGenVertexArrays(n, ids) glGenVertexArraysAPPLE(n, ids)
#define glBindVertexArray(id) glBindVertexArrayAPPLE(id)
#define glDeleteVertexArrays(n, ids) glDeleteVertexArraysAPPLE(n, ids)
#endif
#else
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>
/* This is a workaround needed to compile against nvidia GL headers */
#ifndef GL_ALPHA_BLEND_EQUATION_ATI
#undef GL_VERSION_1_3
#endif
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)glXGetProcAddress((const GLubyte *) #func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#endif
// Check minimum OpenGL header version
#if !defined(GL_VERSION_2_1)
#if defined(GL_VERSION_2_0)
#warning Using OpenGL v2.0 headers with v2.1 overrides. Some features will be disabled.
#if !defined(GL_ARB_framebuffer_object)
// Overrides for GL_EXT_framebuffer_blit
#if !defined(GL_EXT_framebuffer_blit)
#define GL_READ_FRAMEBUFFER_EXT GL_FRAMEBUFFER_EXT
#define GL_DRAW_FRAMEBUFFER_EXT GL_FRAMEBUFFER_EXT
#define glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter)
#endif
// Overrides for GL_EXT_framebuffer_multisample
#if !defined(GL_EXT_framebuffer_multisample)
#define GL_MAX_SAMPLES_EXT 0
#define glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height)
#endif
// Overrides for GL_ARB_pixel_buffer_object
#if !defined(GL_PIXEL_PACK_BUFFER) && defined(GL_PIXEL_PACK_BUFFER_ARB)
#define GL_PIXEL_PACK_BUFFER GL_PIXEL_PACK_BUFFER_ARB
#endif
#endif
#else
#error OpenGL requires v2.1 headers or later.
#endif
#endif
// Textures
#if !defined(GLX_H)
EXTERNOGLEXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) // Core in v1.3
EXTERNOGLEXT(PFNGLACTIVETEXTUREARBPROC, glActiveTextureARB)
#endif
// Blending
EXTERNOGLEXT(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) // Core in v1.4
EXTERNOGLEXT(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate) // Core in v2.0
EXTERNOGLEXT(PFNGLBLENDFUNCSEPARATEEXTPROC, glBlendFuncSeparateEXT)
EXTERNOGLEXT(PFNGLBLENDEQUATIONSEPARATEEXTPROC, glBlendEquationSeparateEXT)
// Shaders
EXTERNOGLEXT(PFNGLCREATESHADERPROC, glCreateShader) // Core in v2.0
EXTERNOGLEXT(PFNGLSHADERSOURCEPROC, glShaderSource) // Core in v2.0
EXTERNOGLEXT(PFNGLCOMPILESHADERPROC, glCompileShader) // Core in v2.0
EXTERNOGLEXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLATTACHSHADERPROC, glAttachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDETACHSHADERPROC, glDetachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLLINKPROGRAMPROC, glLinkProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLUSEPROGRAMPROC, glUseProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERIVPROC, glGetShaderiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETESHADERPROC, glDeleteShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLVALIDATEPROGRAMPROC, glValidateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IPROC, glUniform1i) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IVPROC, glUniform1iv) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1FPROC, glUniform1f) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM2FPROC, glUniform2f) // Core in v2.0
EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0
// Generic vertex attributes
EXTERNOGLEXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) // Core in v2.0
// VAO
EXTERNOGLEXT(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays)
EXTERNOGLEXT(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays)
EXTERNOGLEXT(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray)
// VBO and PBO
EXTERNOGLEXT(PFNGLGENBUFFERSARBPROC, glGenBuffersARB)
EXTERNOGLEXT(PFNGLDELETEBUFFERSARBPROC, glDeleteBuffersARB)
EXTERNOGLEXT(PFNGLBINDBUFFERARBPROC, glBindBufferARB)
EXTERNOGLEXT(PFNGLBUFFERDATAARBPROC, glBufferDataARB)
EXTERNOGLEXT(PFNGLBUFFERSUBDATAARBPROC, glBufferSubDataARB)
EXTERNOGLEXT(PFNGLMAPBUFFERARBPROC, glMapBufferARB)
EXTERNOGLEXT(PFNGLUNMAPBUFFERARBPROC, glUnmapBufferARB)
EXTERNOGLEXT(PFNGLGENBUFFERSPROC, glGenBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLBINDBUFFERPROC, glBindBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERDATAPROC, glBufferData) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERSUBDATAPROC, glBufferSubData) // Core in v1.5
EXTERNOGLEXT(PFNGLMAPBUFFERPROC, glMapBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLUNMAPBUFFERPROC, glUnmapBuffer) // Core in v1.5
// FBO
EXTERNOGLEXT(PFNGLGENFRAMEBUFFERSEXTPROC, glGenFramebuffersEXT)
EXTERNOGLEXT(PFNGLBINDFRAMEBUFFEREXTPROC, glBindFramebufferEXT)
EXTERNOGLEXT(PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC, glFramebufferRenderbufferEXT)
EXTERNOGLEXT(PFNGLFRAMEBUFFERTEXTURE2DEXTPROC, glFramebufferTexture2DEXT)
EXTERNOGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC, glCheckFramebufferStatusEXT)
EXTERNOGLEXT(PFNGLDELETEFRAMEBUFFERSEXTPROC, glDeleteFramebuffersEXT)
EXTERNOGLEXT(PFNGLBLITFRAMEBUFFEREXTPROC, glBlitFramebufferEXT)
// Multisampled FBO
EXTERNOGLEXT(PFNGLGENRENDERBUFFERSEXTPROC, glGenRenderbuffersEXT)
EXTERNOGLEXT(PFNGLBINDRENDERBUFFEREXTPROC, glBindRenderbufferEXT)
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEEXTPROC, glRenderbufferStorageEXT)
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC, glRenderbufferStorageMultisampleEXT)
EXTERNOGLEXT(PFNGLDELETERENDERBUFFERSEXTPROC, glDeleteRenderbuffersEXT)
#else // OGLRENDER_3_2_H
// Basic Functions
EXTERNOGLEXT(PFNGLGETSTRINGIPROC, glGetStringi) // Core in v3.0
// Textures
#if !defined(GLX_H)
EXTERNOGLEXT(PFNGLACTIVETEXTUREPROC, glActiveTexture) // Core in v1.3
#endif
// Blending
EXTERNOGLEXT(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate) // Core in v1.4
EXTERNOGLEXT(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate) // Core in v2.0
// Shaders
EXTERNOGLEXT(PFNGLCREATESHADERPROC, glCreateShader) // Core in v2.0
EXTERNOGLEXT(PFNGLSHADERSOURCEPROC, glShaderSource) // Core in v2.0
EXTERNOGLEXT(PFNGLCOMPILESHADERPROC, glCompileShader) // Core in v2.0
EXTERNOGLEXT(PFNGLCREATEPROGRAMPROC, glCreateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLATTACHSHADERPROC, glAttachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDETACHSHADERPROC, glDetachShader) // Core in v2.0
EXTERNOGLEXT(PFNGLLINKPROGRAMPROC, glLinkProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLUSEPROGRAMPROC, glUseProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERIVPROC, glGetShaderiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETESHADERPROC, glDeleteShader) // Core in v2.0
EXTERNOGLEXT(PFNGLDELETEPROGRAMPROC, glDeleteProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMIVPROC, glGetProgramiv) // Core in v2.0
EXTERNOGLEXT(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog) // Core in v2.0
EXTERNOGLEXT(PFNGLVALIDATEPROGRAMPROC, glValidateProgram) // Core in v2.0
EXTERNOGLEXT(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IPROC, glUniform1i) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1IVPROC, glUniform1iv) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM1FPROC, glUniform1f) // Core in v2.0
EXTERNOGLEXT(PFNGLUNIFORM2FPROC, glUniform2f) // Core in v2.0
EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0
// Generic vertex attributes
EXTERNOGLEXT(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation) // Core in v2.0
EXTERNOGLEXT(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation) // Core in v3.0
EXTERNOGLEXT(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray) // Core in v2.0
EXTERNOGLEXT(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer) // Core in v2.0
// VAO
EXTERNOGLEXT(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays) // Core in v3.0
EXTERNOGLEXT(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays) // Core in v3.0
EXTERNOGLEXT(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray) // Core in v3.0
// VBO and PBO
EXTERNOGLEXT(PFNGLGENBUFFERSPROC, glGenBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLDELETEBUFFERSPROC, glDeleteBuffers) // Core in v1.5
EXTERNOGLEXT(PFNGLBINDBUFFERPROC, glBindBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERDATAPROC, glBufferData) // Core in v1.5
EXTERNOGLEXT(PFNGLBUFFERSUBDATAPROC, glBufferSubData) // Core in v1.5
EXTERNOGLEXT(PFNGLMAPBUFFERPROC, glMapBuffer) // Core in v1.5
EXTERNOGLEXT(PFNGLUNMAPBUFFERPROC, glUnmapBuffer) // Core in v1.5
// FBO
EXTERNOGLEXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) // Core in v3.0
EXTERNOGLEXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) // Core in v3.0
EXTERNOGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) // Core in v3.0
EXTERNOGLEXT(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) // Core in v3.0
EXTERNOGLEXT(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLDRAWBUFFERSPROC, glDrawBuffers) // Core in v2.0
// Multisampled FBO
EXTERNOGLEXT(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) // Core in v3.0
EXTERNOGLEXT(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) // Core in v3.0
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) // Core in v3.0
EXTERNOGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample) // Core in v3.0
EXTERNOGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Core in v3.0
#endif // OGLRENDER_3_2_H
// Define the minimum required OpenGL version for the driver to support
#define OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MAJOR 1
#define OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MINOR 2
#define OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_REVISION 0
#define OGLRENDER_MAX_MULTISAMPLES 16
#define OGLRENDER_VERT_INDEX_BUFFER_SIZE 8192
#define OGLRENDER_VERT_INDEX_BUFFER_COUNT 131072
enum OGLVertexAttributeID
{
OGLVertexAttributeID_Position = 0,
OGLVertexAttributeID_TexCoord0 = 8,
OGLVertexAttributeID_Color = 3,
};
enum OGLTextureUnitID
{
// Main textures will always be on texture unit 0.
OGLTextureUnitID_ToonTable = 1,
OGLTextureUnitID_ClearImage
};
enum OGLErrorCode
{
OGLERROR_NOERR = RENDER3DERROR_NOERR,
OGLERROR_FEATURE_UNSUPPORTED,
OGLERROR_VBO_UNSUPPORTED,
OGLERROR_PBO_UNSUPPORTED,
OGLERROR_SHADER_UNSUPPORTED,
OGLERROR_VAO_UNSUPPORTED,
OGLERROR_FBO_UNSUPPORTED,
OGLERROR_MULTISAMPLED_FBO_UNSUPPORTED,
OGLERROR_SHADER_CREATE_ERROR,
OGLERROR_FBO_CREATE_ERROR
};
struct OGLRenderRef
{
// OpenGL Feature Support
GLint stateTexMirroredRepeat;
// VBO
GLuint vboVertexID;
GLuint iboIndexID;
// PBO
GLuint pboRenderDataID[2];
// FBO
GLuint texClearImageColorID;
GLuint texClearImageDepthStencilID;
GLuint fboClearImageID;
GLuint rboFinalOutputColorID;
GLuint rboFinalOutputDepthStencilID;
GLuint fboFinalOutputID;
// Multisampled FBO
GLuint rboMultisampleColorID;
GLuint rboMultisampleDepthStencilID;
GLuint fboMultisampleRenderID;
GLuint selectedRenderingFBO;
// Shader states
GLuint vertexShaderID;
GLuint fragmentShaderID;
GLuint shaderProgram;
GLint uniformPolyID;
GLint uniformPolyAlpha;
GLint uniformTexScale;
GLint uniformHasTexture;
GLint uniformPolygonMode;
GLint uniformToonShadingMode;
GLint uniformWBuffer;
GLint uniformEnableAlphaTest;
GLint uniformAlphaTestRef;
GLuint texToonTableID;
// VAO
GLuint vaoMainStatesID;
// Textures
std::queue<GLuint> freeTextureIDs;
// Client-side Buffers
GLfloat *color4fBuffer;
DS_ALIGN(16) GLushort vertIndexBuffer[OGLRENDER_VERT_INDEX_BUFFER_COUNT];
};
struct GFX3D_State;
struct VERTLIST;
struct POLYLIST;
struct INDEXLIST;
struct POLY;
class TexCacheItem;
class OpenGLRenderer;
extern GPU3DInterface gpu3Dgl;
@ -49,4 +368,240 @@ extern bool (*oglrender_beginOpenGL)();
//This is called by OGLRender after it is done using opengl.
extern void (*oglrender_endOpenGL)();
// These functions need to be assigned by ports that support using an
// OpenGL 3.2 Core Profile context. The OGLRender_3_2.cpp file includes
// the corresponding functions to assign to each function pointer.
//
// If any of these functions are unassigned, then one of the legacy OpenGL
// renderers will be used instead.
extern void (*OGLLoadEntryPoints_3_2_Func)();
extern void (*OGLCreateRenderer_3_2_Func)(OpenGLRenderer **rendererPtr);
// Lookup Tables
extern CACHE_ALIGN GLfloat material_8bit_to_float[256];
extern CACHE_ALIGN GLuint dsDepthToD24S8_LUT[32768];
extern const GLfloat divide5bitBy31_LUT[32];
FORCEINLINE u32 BGRA8888_32_To_RGBA6665_32Rev(const u32 srcPix);
FORCEINLINE u32 BGRA8888_32Rev_To_RGBA6665_32Rev(const u32 srcPix);
bool IsVersionSupported(unsigned int checkVersionMajor, unsigned int checkVersionMinor, unsigned int checkVersionRevision);
class OpenGLRenderer : public Render3D
{
private:
// Driver's OpenGL Version
unsigned int versionMajor;
unsigned int versionMinor;
unsigned int versionRevision;
protected:
// OpenGL-specific References
OGLRenderRef *ref;
// OpenGL Feature Support
bool isVBOSupported;
bool isPBOSupported;
bool isFBOSupported;
bool isMultisampledFBOSupported;
bool isShaderSupported;
bool isVAOSupported;
// Textures
TexCacheItem *currTexture;
u16 currentToonTable16[32];
bool toonTableNeedsUpdate;
DS_ALIGN(16) u32 GPU_screen3D[2][256 * 192 * sizeof(u32)];
bool gpuScreen3DHasNewData[2];
unsigned int doubleBufferIndex;
u8 clearImageStencilValue;
// OpenGL-specific methods
virtual Render3DError CreateVBOs() = 0;
virtual void DestroyVBOs() = 0;
virtual Render3DError CreatePBOs() = 0;
virtual void DestroyPBOs() = 0;
virtual Render3DError CreateFBOs() = 0;
virtual void DestroyFBOs() = 0;
virtual Render3DError CreateMultisampledFBO() = 0;
virtual void DestroyMultisampledFBO() = 0;
virtual Render3DError CreateShaders(const std::string *vertexShaderProgram, const std::string *fragmentShaderProgram) = 0;
virtual void DestroyShaders() = 0;
virtual Render3DError CreateVAOs() = 0;
virtual void DestroyVAOs() = 0;
virtual Render3DError InitTextures() = 0;
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet) = 0;
virtual Render3DError InitTables() = 0;
virtual Render3DError SetupShaderIO() = 0;
virtual Render3DError CreateToonTable() = 0;
virtual Render3DError DestroyToonTable() = 0;
virtual Render3DError UploadToonTable(const GLushort *toonTableBuffer) = 0;
virtual Render3DError CreateClearImage() = 0;
virtual Render3DError DestroyClearImage() = 0;
virtual Render3DError UploadClearImage(const GLushort *clearImageColorBuffer, const GLint *clearImageDepthBuffer) = 0;
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet) = 0;
virtual Render3DError ExpandFreeTextures() = 0;
virtual Render3DError DownsampleFBO() = 0;
virtual Render3DError ReadBackPixels() = 0;
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D_State *renderState) = 0;
virtual Render3DError PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList) = 0;
virtual Render3DError DoRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList) = 0;
virtual Render3DError PostRender() = 0;
virtual Render3DError EndRender(const u64 frameCount) = 0;
virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u16 *__restrict depthBuffer, const u8 clearStencil, const u8 xScroll, const u8 yScroll) = 0;
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer) = 0;
virtual Render3DError ClearUsingImage() const = 0;
virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil) const = 0;
virtual Render3DError SetupPolygon(const POLY *thePoly) = 0;
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing) = 0;
virtual Render3DError SetupViewport(const POLY *thePoly) = 0;
public:
OpenGLRenderer();
virtual ~OpenGLRenderer() {};
virtual Render3DError InitExtensions() = 0;
virtual Render3DError Reset() = 0;
virtual Render3DError RenderFinish() = 0;
virtual Render3DError DeleteTexture(const TexCacheItem *item) = 0;
bool IsExtensionPresent(const std::set<std::string> *oglExtensionSet, const std::string extensionName) const;
bool ValidateShaderCompile(GLuint theShader) const;
bool ValidateShaderProgramLink(GLuint theProgram) const;
void GetVersion(unsigned int *major, unsigned int *minor, unsigned int *revision) const;
void SetVersion(unsigned int major, unsigned int minor, unsigned int revision);
void ConvertFramebuffer(const u32 *__restrict srcBuffer, u32 *dstBuffer);
};
class OpenGLRenderer_1_2 : public OpenGLRenderer
{
protected:
// OpenGL-specific methods
virtual Render3DError CreateVBOs();
virtual void DestroyVBOs();
virtual Render3DError CreatePBOs();
virtual void DestroyPBOs();
virtual Render3DError CreateFBOs();
virtual void DestroyFBOs();
virtual Render3DError CreateMultisampledFBO();
virtual void DestroyMultisampledFBO();
virtual Render3DError CreateShaders(const std::string *vertexShaderProgram, const std::string *fragmentShaderProgram);
virtual void DestroyShaders();
virtual Render3DError CreateVAOs();
virtual void DestroyVAOs();
virtual Render3DError InitTextures();
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual Render3DError InitTables();
virtual Render3DError SetupShaderIO();
virtual Render3DError CreateToonTable();
virtual Render3DError DestroyToonTable();
virtual Render3DError UploadToonTable(const GLushort *toonTableBuffer);
virtual Render3DError CreateClearImage();
virtual Render3DError DestroyClearImage();
virtual Render3DError UploadClearImage(const GLushort *clearImageColorBuffer, const GLint *clearImageDepthBuffer);
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError ExpandFreeTextures();
virtual Render3DError DownsampleFBO();
virtual Render3DError ReadBackPixels();
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError DoRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError PostRender();
virtual Render3DError EndRender(const u64 frameCount);
virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u16 *__restrict depthBuffer, const u8 clearStencil, const u8 xScroll, const u8 yScroll);
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError ClearUsingImage() const;
virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil) const;
virtual Render3DError SetupPolygon(const POLY *thePoly);
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing);
virtual Render3DError SetupViewport(const POLY *thePoly);
public:
OpenGLRenderer_1_2();
~OpenGLRenderer_1_2();
virtual Render3DError InitExtensions();
virtual Render3DError Reset();
virtual Render3DError RenderFinish();
virtual Render3DError DeleteTexture(const TexCacheItem *item);
};
class OpenGLRenderer_1_3 : public OpenGLRenderer_1_2
{
protected:
virtual Render3DError CreateToonTable();
virtual Render3DError DestroyToonTable();
virtual Render3DError UploadToonTable(const GLushort *toonTableBuffer);
virtual Render3DError CreateClearImage();
virtual Render3DError DestroyClearImage();
virtual Render3DError UploadClearImage(const GLushort *clearImageColorBuffer, const GLint *clearImageDepthBuffer);
};
class OpenGLRenderer_1_4 : public OpenGLRenderer_1_3
{
protected:
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
};
class OpenGLRenderer_1_5 : public OpenGLRenderer_1_4
{
protected:
virtual Render3DError CreateVBOs();
virtual void DestroyVBOs();
virtual Render3DError CreatePBOs();
virtual void DestroyPBOs();
virtual Render3DError CreateVAOs();
virtual Render3DError ReadBackPixels();
virtual Render3DError PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError PostRender();
public:
~OpenGLRenderer_1_5();
virtual Render3DError RenderFinish();
};
class OpenGLRenderer_2_0 : public OpenGLRenderer_1_5
{
protected:
virtual Render3DError InitExtensions();
virtual Render3DError InitFinalRenderStates(const std::set<std::string> *oglExtensionSet);
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError DoRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError PostRender();
virtual Render3DError SetupPolygon(const POLY *thePoly);
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing);
};
class OpenGLRenderer_2_1 : public OpenGLRenderer_2_0
{
protected:
virtual Render3DError ReadBackPixels();
public:
virtual Render3DError RenderFinish();
};
#endif

View File

@ -0,0 +1,626 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "OGLRender_3_2.h"
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "gfx3d.h"
#include "NDSSystem.h"
#include "texcache.h"
//------------------------------------------------------------
// Basic Functions
OGLEXT(PFNGLGETSTRINGIPROC, glGetStringi) // Core in v3.0
// Shaders
OGLEXT(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation) // Core in v3.0
// FBO
OGLEXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) // Core in v3.0
OGLEXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) // Core in v3.0
OGLEXT(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) // Core in v3.0
OGLEXT(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) // Core in v3.0
OGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) // Core in v3.0
OGLEXT(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) // Core in v3.0
OGLEXT(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer) // Core in v3.0
OGLEXT(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) // Core in v3.0
OGLEXT(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) // Core in v3.0
OGLEXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) // Core in v3.0
OGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample) // Core in v3.0
OGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Core in v3.0
void OGLLoadEntryPoints_3_2()
{
// Basic Functions
INITOGLEXT(PFNGLGETSTRINGIPROC, glGetStringi)
// Shaders
INITOGLEXT(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation)
// FBO
INITOGLEXT(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers) // Promote to core version
INITOGLEXT(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer) // Promote to core version
INITOGLEXT(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer) // Promote to core version
INITOGLEXT(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D) // Promote to core version
INITOGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus) // Promote to core version
INITOGLEXT(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers) // Promote to core version
INITOGLEXT(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer) // Promote to core version
INITOGLEXT(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers) // Promote to core version
INITOGLEXT(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer) // Promote to core version
INITOGLEXT(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage) // Promote to core version
INITOGLEXT(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample) // Promote to core version
INITOGLEXT(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers) // Promote to core version
}
// Vertex Shader GLSL 1.50
static const char *vertexShader_150 = {"\
#version 150 \n\
\n\
in vec4 inPosition; \n\
in vec2 inTexCoord0; \n\
in vec3 inColor; \n\
\n\
uniform float polyAlpha; \n\
uniform vec2 texScale; \n\
\n\
out vec4 vtxPosition; \n\
out vec2 vtxTexCoord; \n\
out vec4 vtxColor; \n\
\n\
void main() \n\
{ \n\
mat2 texScaleMtx = mat2( vec2(texScale.x, 0.0), \n\
vec2( 0.0, texScale.y)); \n\
\n\
vtxPosition = inPosition; \n\
vtxTexCoord = texScaleMtx * inTexCoord0; \n\
vtxColor = vec4(inColor * 4.0, polyAlpha); \n\
\n\
gl_Position = vtxPosition; \n\
} \n\
"};
// Fragment Shader GLSL 1.50
static const char *fragmentShader_150 = {"\
#version 150 \n\
\n\
in vec4 vtxPosition; \n\
in vec2 vtxTexCoord; \n\
in vec4 vtxColor; \n\
\n\
uniform sampler2D texMainRender; \n\
uniform sampler1D texToonTable; \n\
uniform int polyID; \n\
uniform bool hasTexture; \n\
uniform int polygonMode; \n\
uniform int toonShadingMode; \n\
uniform int oglWBuffer; \n\
uniform bool enableAlphaTest; \n\
uniform float alphaTestRef; \n\
\n\
out vec4 outFragColor; \n\
\n\
void main() \n\
{ \n\
vec4 texColor = vec4(1.0, 1.0, 1.0, 1.0); \n\
vec4 flagColor; \n\
float flagDepth; \n\
\n\
if(hasTexture) \n\
{ \n\
texColor = texture(texMainRender, vtxTexCoord); \n\
} \n\
\n\
flagColor = texColor; \n\
\n\
if(polygonMode == 0) \n\
{ \n\
flagColor = vtxColor * texColor; \n\
} \n\
else if(polygonMode == 1) \n\
{ \n\
if (texColor.a == 0.0 || !hasTexture) \n\
{ \n\
flagColor.rgb = vtxColor.rgb; \n\
} \n\
else if (texColor.a == 1.0) \n\
{ \n\
flagColor.rgb = texColor.rgb; \n\
} \n\
else \n\
{ \n\
flagColor.rgb = texColor.rgb * (1.0-texColor.a) + vtxColor.rgb * texColor.a; \n\
} \n\
\n\
flagColor.a = vtxColor.a; \n\
} \n\
else if(polygonMode == 2) \n\
{ \n\
vec3 toonColor = vec3(texture(texToonTable, vtxColor.r).rgb); \n\
\n\
if (toonShadingMode == 0) \n\
{ \n\
flagColor.rgb = texColor.rgb * toonColor.rgb; \n\
} \n\
else \n\
{ \n\
flagColor.rgb = texColor.rgb * vtxColor.rgb + toonColor.rgb; \n\
} \n\
\n\
flagColor.a = texColor.a * vtxColor.a; \n\
} \n\
else if(polygonMode == 3) \n\
{ \n\
if (polyID != 0) \n\
{ \n\
flagColor = vtxColor; \n\
} \n\
} \n\
\n\
if (flagColor.a == 0.0 || (enableAlphaTest && flagColor.a < alphaTestRef)) \n\
{ \n\
discard; \n\
} \n\
\n\
if (oglWBuffer == 1) \n\
{ \n\
// TODO \n\
flagDepth = (vtxPosition.z / vtxPosition.w) * 0.5 + 0.5; \n\
} \n\
else \n\
{ \n\
flagDepth = (vtxPosition.z / vtxPosition.w) * 0.5 + 0.5; \n\
} \n\
\n\
outFragColor = flagColor; \n\
gl_FragDepth = flagDepth; \n\
} \n\
"};
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr)
{
if (IsVersionSupported(3, 2, 0))
{
*rendererPtr = new OpenGLRenderer_3_2;
(*rendererPtr)->SetVersion(3, 2, 0);
}
}
OpenGLRenderer_3_2::~OpenGLRenderer_3_2()
{
glFinish();
DestroyVAOs();
DestroyFBOs();
DestroyMultisampledFBO();
}
Render3DError OpenGLRenderer_3_2::InitExtensions()
{
Render3DError error = OGLERROR_NOERR;
OGLRenderRef &OGLRef = *this->ref;
// Load shader programs
const std::string vertexShaderProgram = vertexShader_150;
const std::string fragmentShaderProgram = fragmentShader_150;
// Get OpenGL extensions
std::set<std::string> oglExtensionSet;
this->GetExtensionSet(&oglExtensionSet);
// Initialize OpenGL
this->InitTables();
this->isShaderSupported = true;
error = this->CreateShaders(&vertexShaderProgram, &fragmentShaderProgram);
if (error != OGLERROR_NOERR)
{
this->isShaderSupported = false;
if (error == OGLERROR_SHADER_CREATE_ERROR)
{
// Return on OGLERROR_SHADER_CREATE_ERROR, since a v2.0 driver should be able to
// support shaders.
return error;
}
}
else
{
this->CreateToonTable();
}
this->isVBOSupported = true;
this->CreateVBOs();
this->isPBOSupported = true;
this->CreatePBOs();
this->isVAOSupported = true;
this->CreateVAOs();
this->isFBOSupported = true;
error = this->CreateFBOs();
if (error != OGLERROR_NOERR)
{
OGLRef.fboFinalOutputID = 0;
this->isFBOSupported = false;
if (error == OGLERROR_FBO_CREATE_ERROR)
{
// Return on OGLERROR_FBO_CREATE_ERROR, since a v3.0 driver should be able to
// support FBOs.
return error;
}
}
this->isMultisampledFBOSupported = true;
error = this->CreateMultisampledFBO();
if (error != OGLERROR_NOERR)
{
OGLRef.selectedRenderingFBO = 0;
this->isMultisampledFBOSupported = false;
if (error == OGLERROR_FBO_CREATE_ERROR)
{
// Return on OGLERROR_FBO_CREATE_ERROR, since a v3.0 driver should be able to
// support FBOs.
return error;
}
}
this->InitTextures();
this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::CreateFBOs()
{
OGLRenderRef &OGLRef = *this->ref;
// Set up FBO render targets
this->CreateClearImage();
glGenRenderbuffers(1, &OGLRef.rboFinalOutputColorID);
glGenRenderbuffers(1, &OGLRef.rboFinalOutputDepthStencilID);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFinalOutputColorID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, 256, 192);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboFinalOutputDepthStencilID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 256, 192);
// Set up FBOs
glGenFramebuffers(1, &OGLRef.fboClearImageID);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboClearImageID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGLRef.texClearImageColorID, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, OGLRef.texClearImageDepthStencilID, 0);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboClearImageID);
this->DestroyClearImage();
glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputColorID);
glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputDepthStencilID);
return OGLERROR_FBO_CREATE_ERROR;
}
// Set up final output FBO
glGenFramebuffers(1, &OGLRef.fboFinalOutputID);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboFinalOutputID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboFinalOutputColorID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboFinalOutputDepthStencilID);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboClearImageID);
this->DestroyClearImage();
glDeleteFramebuffers(1, &OGLRef.fboFinalOutputID);
glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputColorID);
glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputDepthStencilID);
OGLRef.fboFinalOutputID = 0;
return OGLERROR_FBO_CREATE_ERROR;
}
glReadBuffer(GL_COLOR_ATTACHMENT0);
INFO("OpenGL: Successfully created FBOs.\n");
return OGLERROR_NOERR;
}
void OpenGLRenderer_3_2::DestroyFBOs()
{
if (!this->isFBOSupported)
{
return;
}
OGLRenderRef &OGLRef = *this->ref;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboClearImageID);
this->DestroyClearImage();
glDeleteFramebuffers(1, &OGLRef.fboFinalOutputID);
glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputColorID);
glDeleteRenderbuffers(1, &OGLRef.rboFinalOutputDepthStencilID);
this->isFBOSupported = false;
}
Render3DError OpenGLRenderer_3_2::CreateMultisampledFBO()
{
// Check the maximum number of samples that the GPU supports and use that.
// Since our target resolution is only 256x192 pixels, using the most samples
// possible is the best thing to do.
GLint maxSamples = 0;
glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
if (maxSamples < 2)
{
INFO("OpenGL: GPU does not support at least 2x multisampled FBOs. Multisample antialiasing will be disabled.\n");
return OGLERROR_FEATURE_UNSUPPORTED;
}
else if (maxSamples > OGLRENDER_MAX_MULTISAMPLES)
{
maxSamples = OGLRENDER_MAX_MULTISAMPLES;
}
OGLRenderRef &OGLRef = *this->ref;
// Set up FBO render targets
glGenRenderbuffers(1, &OGLRef.rboMultisampleColorID);
glGenRenderbuffers(1, &OGLRef.rboMultisampleDepthStencilID);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMultisampleColorID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_RGBA, 256, 192);
glBindRenderbuffer(GL_RENDERBUFFER, OGLRef.rboMultisampleDepthStencilID);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, maxSamples, GL_DEPTH24_STENCIL8, 256, 192);
// Set up multisampled rendering FBO
glGenFramebuffers(1, &OGLRef.fboMultisampleRenderID);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboMultisampleRenderID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OGLRef.rboMultisampleColorID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OGLRef.rboMultisampleDepthStencilID);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboMultisampleRenderID);
glDeleteRenderbuffers(1, &OGLRef.rboMultisampleColorID);
glDeleteRenderbuffers(1, &OGLRef.rboMultisampleDepthStencilID);
INFO("OpenGL: Failed to create multisampled FBO. Multisample antialiasing will be disabled.\n");
return OGLERROR_FBO_CREATE_ERROR;
}
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboFinalOutputID);
INFO("OpenGL: Successfully created multisampled FBO.\n");
return OGLERROR_NOERR;
}
void OpenGLRenderer_3_2::DestroyMultisampledFBO()
{
if (!this->isMultisampledFBOSupported)
{
return;
}
OGLRenderRef &OGLRef = *this->ref;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &OGLRef.fboMultisampleRenderID);
glDeleteRenderbuffers(1, &OGLRef.rboMultisampleColorID);
glDeleteRenderbuffers(1, &OGLRef.rboMultisampleDepthStencilID);
this->isMultisampledFBOSupported = false;
}
Render3DError OpenGLRenderer_3_2::CreateVAOs()
{
OGLRenderRef &OGLRef = *this->ref;
glGenVertexArrays(1, &OGLRef.vaoMainStatesID);
glBindVertexArray(OGLRef.vaoMainStatesID);
glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboVertexID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboIndexID);
glEnableVertexAttribArray(OGLVertexAttributeID_Position);
glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
glEnableVertexAttribArray(OGLVertexAttributeID_Color);
glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord));
glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord));
glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color));
glBindVertexArray(0);
return OGLERROR_NOERR;
}
void OpenGLRenderer_3_2::DestroyVAOs()
{
if (!this->isVAOSupported)
{
return;
}
glBindVertexArray(0);
glDeleteVertexArrays(1, &this->ref->vaoMainStatesID);
this->isVAOSupported = false;
}
Render3DError OpenGLRenderer_3_2::SetupShaderIO()
{
OGLRenderRef &OGLRef = *this->ref;
glBindAttribLocation(OGLRef.shaderProgram, OGLVertexAttributeID_Position, "inPosition");
glBindAttribLocation(OGLRef.shaderProgram, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
glBindAttribLocation(OGLRef.shaderProgram, OGLVertexAttributeID_Color, "inColor");
glBindFragDataLocation(OGLRef.shaderProgram, 0, "outFragColor");
return OGLERROR_NOERR;
}
void OpenGLRenderer_3_2::GetExtensionSet(std::set<std::string> *oglExtensionSet)
{
GLint extensionCount = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
for (unsigned int i = 0; i < extensionCount; i++)
{
std::string extensionName = std::string((const char *)glGetStringi(GL_EXTENSIONS, i));
oglExtensionSet->insert(extensionName);
}
}
Render3DError OpenGLRenderer_3_2::DownsampleFBO()
{
OGLRenderRef &OGLRef = *this->ref;
if (!this->isMultisampledFBOSupported || OGLRef.selectedRenderingFBO != OGLRef.fboMultisampleRenderID)
{
return OGLERROR_NOERR;
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.fboFinalOutputID);
glBlitFramebuffer(0, 0, 256, 192, 0, 0, 256, 192, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.fboFinalOutputID);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State *renderState)
{
OGLRenderRef &OGLRef = *this->ref;
glUniform1i(OGLRef.uniformEnableAlphaTest, renderState->enableAlphaTest ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformAlphaTestRef, divide5bitBy31_LUT[renderState->alphaTestRef]);
glUniform1i(OGLRef.uniformToonShadingMode, renderState->shading);
glUniform1i(OGLRef.uniformWBuffer, renderState->wbuffer);
if(renderState->enableAlphaBlending)
{
glEnable(GL_BLEND);
}
else
{
glDisable(GL_BLEND);
}
if (this->isMultisampledFBOSupported)
{
OGLRef.selectedRenderingFBO = CommonSettings.GFX3D_Renderer_Multisample ? OGLRef.fboMultisampleRenderID : OGLRef.fboFinalOutputID;
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
const GLenum drawBufferList = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, &drawBufferList);
}
glDepthMask(GL_TRUE);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList)
{
OGLRenderRef &OGLRef = *this->ref;
const unsigned int polyCount = polyList->count;
unsigned int vertIndexCount = 0;
// Set up vertices
for(unsigned int i = 0; i < polyCount; i++)
{
const POLY *poly = &polyList->list[indexList->list[i]];
const unsigned int polyType = poly->type;
for(unsigned int j = 0; j < polyType; j++)
{
const GLushort vertIndex = poly->vertIndexes[j];
// While we're looping through our vertices, add each vertex index to
// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
// vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions.
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
if (poly->vtxFormat == GFX3D_QUADS || poly->vtxFormat == GFX3D_QUAD_STRIP)
{
if (j == 2)
{
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
}
else if (j == 3)
{
OGLRef.vertIndexBuffer[vertIndexCount++] = poly->vertIndexes[0];
}
}
}
}
// Assign vertex attributes
glBindVertexArray(OGLRef.vaoMainStatesID);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * vertList->count, vertList);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, vertIndexCount * sizeof(GLushort), OGLRef.vertIndexBuffer);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::PostRender()
{
// Disable vertex attributes
glBindVertexArray(0);
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::ClearUsingImage() const
{
OGLRenderRef &OGLRef = *this->ref;
glBindFramebuffer(GL_READ_FRAMEBUFFER, OGLRef.fboClearImageID);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
glBlitFramebuffer(0, 0, 256, 192, 0, 0, 256, 192, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_FRAMEBUFFER, OGLRef.selectedRenderingFBO);
return OGLERROR_NOERR;
}

View File

@ -0,0 +1,86 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OGLRENDER_3_2_H
#define OGLRENDER_3_2_H
#if defined(_WIN32) && !defined(WXPORT)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/gl.h>
#include <GL/glcorearb.h>
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)wglGetProcAddress(#func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#elif defined(__APPLE__)
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
// Ignore dynamic linking on Apple OS
#define OGLEXT(procPtr, func)
#define INITOGLEXT(procPtr, func)
#define EXTERNOGLEXT(procPtr, func)
#else
#include <GL/gl.h>
#include <GL/glcorearb.h>
#include <GL/glx.h>
#define OGLEXT(procPtr, func) procPtr func = NULL;
#define INITOGLEXT(procPtr, func) func = (procPtr)glXGetProcAddress((const GLubyte *) #func);
#define EXTERNOGLEXT(procPtr, func) extern procPtr func;
#endif
// Check minimum OpenGL header version
#if !defined(GL_VERSION_3_2)
#error OpenGL requires v3.2 headers or later.
#endif
#include "OGLRender.h"
void OGLLoadEntryPoints_3_2();
void OGLCreateRenderer_3_2(OpenGLRenderer **rendererPtr);
class OpenGLRenderer_3_2 : public OpenGLRenderer_2_1
{
protected:
virtual Render3DError InitExtensions();
virtual Render3DError CreateFBOs();
virtual void DestroyFBOs();
virtual Render3DError CreateMultisampledFBO();
virtual void DestroyMultisampledFBO();
virtual Render3DError CreateVAOs();
virtual void DestroyVAOs();
virtual Render3DError SetupShaderIO();
virtual void GetExtensionSet(std::set<std::string> *oglExtensionSet);
virtual Render3DError DownsampleFBO();
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError PostRender();
virtual Render3DError ClearUsingImage() const;
public:
~OpenGLRenderer_3_2();
};
#endif

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2009 DeSmuME team
Copyright (C) 2008-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -18,6 +18,7 @@
#include "render3D.h"
#include "gfx3d.h"
#include "MMU.h"
#include "texcache.h"
int cur3DCore = GPU3D_NULL;
@ -92,3 +93,146 @@ bool NDS_3D_ChangeCore(int newCore)
}
return true;
}
Render3DError Render3D::BeginRender(const GFX3D_State *renderState)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::DoRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::PostRender()
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::EndRender(const u64 frameCount)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::UpdateClearImage(const u16 *__restrict colorBuffer, const u16 *__restrict depthBuffer, const u8 clearStencil, const u8 xScroll, const u8 yScroll)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::UpdateToonTable(const u16 *toonTableBuffer)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::ClearFramebuffer(const GFX3D_State *renderState)
{
Render3DError error = RENDER3DERROR_NOERR;
struct GFX3D_ClearColor
{
u8 r;
u8 g;
u8 b;
u8 a;
} clearColor;
clearColor.r = renderState->clearColor & 0x1F;
clearColor.g = (renderState->clearColor >> 5) & 0x1F;
clearColor.b = (renderState->clearColor >> 10) & 0x1F;
clearColor.a = (renderState->clearColor >> 16) & 0x1F;
const u8 clearStencil = (renderState->clearColor >> 24) & 0x3F;
if (renderState->enableClearImage)
{
const u16 *__restrict clearColorBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[2];
const u16 *__restrict clearDepthBuffer = (u16 *__restrict)MMU.texInfo.textureSlotAddr[3];
const u16 scrollBits = T1ReadWord(MMU.ARM9_REG, 0x356); //CLRIMAGE_OFFSET
const u8 xScroll = scrollBits & 0xFF;
const u8 yScroll = (scrollBits >> 8) & 0xFF;
error = this->UpdateClearImage(clearColorBuffer, clearDepthBuffer, clearStencil, xScroll, yScroll);
if (error == RENDER3DERROR_NOERR)
{
error = this->ClearUsingImage();
}
else
{
error = this->ClearUsingValues(clearColor.r, clearColor.g, clearColor.b, clearColor.a, renderState->clearDepth, clearStencil);
}
}
else
{
error = this->ClearUsingValues(clearColor.r, clearColor.g, clearColor.b, clearColor.a, renderState->clearDepth, clearStencil);
}
return error;
}
Render3DError Render3D::ClearUsingImage() const
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil) const
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::SetupPolygon(const POLY *thePoly)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::SetupTexture(const POLY *thePoly, bool enableTexturing)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::SetupViewport(const POLY *thePoly)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::Reset()
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::Render(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, const u64 frameCount)
{
Render3DError error = RENDER3DERROR_NOERR;
error = this->BeginRender(renderState);
if (error != RENDER3DERROR_NOERR)
{
return error;
}
this->UpdateToonTable(renderState->u16ToonTable);
this->ClearFramebuffer(renderState);
this->PreRender(renderState, vertList, polyList, indexList);
this->DoRender(renderState, vertList, polyList, indexList);
this->PostRender();
this->EndRender(frameCount);
return error;
}
Render3DError Render3D::RenderFinish()
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::VramReconfigureSignal()
{
TexCache_Invalidate();
return RENDER3DERROR_NOERR;
}

View File

@ -1,6 +1,6 @@
/*
Copyright (C) 2006-2007 shash
Copyright (C) 2007-2012 DeSmuME team
Copyright (C) 2007-2013 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -19,6 +19,7 @@
#ifndef RENDER3D_H
#define RENDER3D_H
#include "gfx3d.h"
#include "types.h"
//not using this right now
@ -73,5 +74,39 @@ void Default3D_VramReconfigureSignal();
void NDS_3D_SetDriver (int core3DIndex);
bool NDS_3D_ChangeCore(int newCore);
enum Render3DErrorCode
{
RENDER3DERROR_NOERR = 0
};
typedef int Render3DError;
class Render3D
{
protected:
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError PreRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError DoRender(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError PostRender();
virtual Render3DError EndRender(const u64 frameCount);
virtual Render3DError UpdateClearImage(const u16 *__restrict colorBuffer, const u16 *__restrict depthBuffer, const u8 clearStencil, const u8 xScroll, const u8 yScroll);
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError ClearFramebuffer(const GFX3D_State *renderState);
virtual Render3DError ClearUsingImage() const;
virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearStencil) const;
virtual Render3DError SetupPolygon(const POLY *thePoly);
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing);
virtual Render3DError SetupViewport(const POLY *thePoly);
public:
virtual Render3DError Reset();
virtual Render3DError Render(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, const u64 frameCount);
virtual Render3DError RenderFinish();
virtual Render3DError VramReconfigureSignal();
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff