1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00
Beef/BeefySysLib/platform/sdl/GLRenderDevice.cpp

855 lines
27 KiB
C++
Raw Normal View History

2019-08-23 11:56:54 -07:00
#include "GLRenderDevice.h"
#include "SdlBFApp.h"
#include "BFWindow.h"
#include "img/ImageData.h"
#include "util/PerfTimer.h"
2022-11-03 10:58:24 -07:00
#include <SDL2/SDL_video.h>
2019-08-23 11:56:54 -07:00
USING_NS_BF;
#ifndef NOT_IMPL
2019-08-23 11:56:54 -07:00
#define NOT_IMPL throw "Not implemented"
#endif
2019-08-23 11:56:54 -07:00
2022-11-03 10:58:24 -07:00
#pragma comment(lib, "SDL2.lib")
2019-08-23 11:56:54 -07:00
#ifdef _WIN32
#ifdef BF_PLATFORM_OPENGL_ES2
#pragma comment(lib, "libEGL.lib")
#pragma comment(lib, "libGLESv2.lib")
#else
#pragma comment(lib, "opengl32.lib")
#endif
#endif
/*#if SDL_VIDEO_DRIVER_WINDOWS
#define APIENTRYP __stdcall *
#elif defined BF_PLATFORM_OPENGL_ES2
#define APIENTRYP *
#endif*/
#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
#if defined BF_PLATFORM_OPENGL_ES2
#define APIENTRYP BF_CALLTYPE *
#endif
2022-11-03 10:58:24 -07:00
typedef void (APIENTRYP GL_DEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam);
static void (APIENTRYP bf_glDebugMessageCallback)(GL_DEBUGPROC callback, const void* userParam);
static void (APIENTRYP bf_glActiveTexture)(GLenum texture);
static void (APIENTRYP bf_glGenVertexArrays)(GLsizei n, GLuint* buffers);
static void (APIENTRYP bf_glBindVertexArray)(GLenum target);
2019-08-23 11:56:54 -07:00
static void (APIENTRYP bf_glGenBuffers)(GLsizei n, GLuint *buffers);
static void (APIENTRYP bf_glBindBuffer)(GLenum target, GLuint buffer);
static void (APIENTRYP bf_glBufferData)(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
static void (APIENTRYP bf_glDeleteBuffers)(GLsizei n, const GLuint *buffers);
static GLvoid* (APIENTRYP bf_glMapBuffer)(GLenum target, GLenum access);
static GLboolean (APIENTRYP bf_glUnmapBuffer)(GLenum target);
static void (APIENTRYP bf_glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params);
static void (APIENTRYP bf_glColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
static void (APIENTRYP bf_glDrawArrays)(GLenum mode, GLint first, GLsizei count);
static void (APIENTRYP bf_glEdgeFlagPointer)(GLsizei stride, const GLboolean *pointer);
static void (APIENTRYP bf_glGetPointerv)(GLenum pname, GLvoid* *params);
static void (APIENTRYP bf_glIndexPointer)(GLenum type, GLsizei stride, const GLvoid *pointer);
static void (APIENTRYP bf_glNormalPointer)(GLenum type, GLsizei stride, const GLvoid *pointer);
static void (APIENTRYP bf_glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
static void (APIENTRYP bf_glVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
static void (APIENTRYP bf_glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
static void (APIENTRYP bf_glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices);
static void (APIENTRYP bf_glAttachShader)(GLuint program, GLuint shader);
static void (APIENTRYP bf_glBindAttribLocation)(GLuint program, GLuint index, const GLchar *name);
static void (APIENTRYP bf_glCompileShader)(GLuint shader);
static GLuint (APIENTRYP bf_glCreateProgram)(void);
static GLuint (APIENTRYP bf_glCreateShader)(GLenum type);
static void (APIENTRYP bf_glDeleteProgram)(GLuint program);
static void (APIENTRYP bf_glDeleteShader)(GLuint shader);
static void (APIENTRYP bf_glDetachShader)(GLuint program, GLuint shader);
static void (APIENTRYP bf_glDisableVertexAttribArray)(GLuint index);
static void (APIENTRYP bf_glEnableVertexAttribArray)(GLuint index);
static void (APIENTRYP bf_glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
static void (APIENTRYP bf_glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
static void (APIENTRYP bf_glGetAttachedShaders)(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *obj);
static GLint (APIENTRYP bf_glGetAttribLocation)(GLuint program, const GLchar *name);
static void (APIENTRYP bf_glGetProgramiv)(GLuint program, GLenum pname, GLint *params);
static void (APIENTRYP bf_glGetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
static void (APIENTRYP bf_glGetShaderiv)(GLuint shader, GLenum pname, GLint *params);
static void (APIENTRYP bf_glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
static void (APIENTRYP bf_glGetShaderSource)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
static GLint (APIENTRYP bf_glGetUniformLocation)(GLuint program, const GLchar *name);
static void (APIENTRYP bf_glGetUniformfv)(GLuint program, GLint location, GLfloat *params);
static void (APIENTRYP bf_glGetUniformiv)(GLuint program, GLint location, GLint *params);
static void (APIENTRYP bf_glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat *params);
static void (APIENTRYP bf_glGetVertexAttribiv)(GLuint index, GLenum pname, GLint *params);
static void (APIENTRYP bf_glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid* *pointer);
static GLboolean (APIENTRYP bf_glIsProgram)(GLuint program);
static GLboolean (APIENTRYP bf_glIsShader)(GLuint shader);
static void (APIENTRYP bf_glLinkProgram)(GLuint program);
static void (APIENTRYP bf_glShaderSource)(GLuint shader, GLsizei count, const GLchar* *string, const GLint *length);
static void (APIENTRYP bf_glUseProgram)(GLuint program);
static void (APIENTRYP bf_glUniform1f)(GLint location, GLfloat v0);
static void (APIENTRYP bf_glUniform2f)(GLint location, GLfloat v0, GLfloat v1);
static void (APIENTRYP bf_glUniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
static void (APIENTRYP bf_glUniform4f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
static void (APIENTRYP bf_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
static void (APIENTRYP bf_glGetObjectParameterivARB)(GLint obj, GLenum pname, GLint *params);
static void (APIENTRYP bf_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
static void (APIENTRYP bf_glClientActiveTexture)(GLenum texture);
#if !defined BF_PLATFORM_OPENGL_ES2
static void (APIENTRYP bf_glGetVertexAttribdv)(GLuint index, GLenum pname, GLdouble *params);
#endif
///
static int GetPowerOfTwo(int input)
{
int value = 1;
while (value < input)
2022-11-03 10:58:24 -07:00
value <<= 1;
2019-08-23 11:56:54 -07:00
return value;
}
#define GLFAILED(check) ((hr = (check)) != 0)
#define GLCHECK(check) if ((check) != 0) BF_FATAL("GL call failed")
static void CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, float matrix[4][4])
2022-11-03 10:58:24 -07:00
{
memset(matrix, 0, sizeof(float) * 4 * 4);
2019-08-23 11:56:54 -07:00
float invRL = 1.0f / (right - left);
float invTB = 1.0f / (top - bottom);
float invFN = 1.0f / (zFar - zNear);
2022-11-03 10:58:24 -07:00
2019-08-23 11:56:54 -07:00
matrix[0][0] = 2.0f * invRL;
matrix[1][1] = 2.0f * invTB;
matrix[2][2] = -2.0f * invFN;
matrix[3][3] = 1.0f;
matrix[3][0] = -(right + left) * invRL;
matrix[3][1] = -(top + bottom) * invTB;
matrix[3][2] = -(zFar + zNear) * invFN;
}
GLShaderParam::GLShaderParam()
{
mGLVariable = 0;
2019-08-23 11:56:54 -07:00
}
GLShaderParam::~GLShaderParam()
2022-11-03 10:58:24 -07:00
{
2019-08-23 11:56:54 -07:00
}
void GLShaderParam::SetTexture(Texture* texture)
{
NOT_IMPL;
//GLTexture* dXTexture = (GLTexture*) texture;
//GLCHECK(mGLVariable->AsShaderResource()->SetResource(dXTexture->mGLTexture));
}
void GLShaderParam::SetFloat4(float x, float y, float z, float w)
{
NOT_IMPL;
2022-11-03 10:58:24 -07:00
//float v[4] = {x, y, z, w};
2019-08-23 11:56:54 -07:00
//GLCHECK(mGLVariable->AsVector()->SetFloatVector(v));
}
///
GLShader::GLShader()
2022-11-03 10:58:24 -07:00
{
2019-08-23 11:56:54 -07:00
}
GLShader::~GLShader()
{
2022-11-03 10:58:24 -07:00
for (auto paramKV : mParamsMap)
2019-08-23 11:56:54 -07:00
{
2022-11-03 10:58:24 -07:00
delete paramKV.mValue;
2019-08-23 11:56:54 -07:00
}
}
2022-11-03 10:58:24 -07:00
ShaderParam* GLShader::GetShaderParam(const StringImpl& name)
2019-08-23 11:56:54 -07:00
{
NOT_IMPL;
return NULL;
}
///
GLTexture::GLTexture()
{
2022-11-03 10:58:24 -07:00
mGLTexture = 0;
mGLTexture2 = 0;
//mGLRenderTargetView = NULL;
2019-08-23 11:56:54 -07:00
mRenderDevice = NULL;
2022-11-03 10:58:24 -07:00
mImageData = NULL;
2019-08-23 11:56:54 -07:00
}
GLTexture::~GLTexture()
{
2022-11-03 10:58:24 -07:00
if (mImageData != NULL)
mImageData->Deref();
2019-08-23 11:56:54 -07:00
//if (mGLTexture != NULL)
//mGLTexture->Release();
}
void GLTexture::PhysSetAsTarget()
2022-11-03 10:58:24 -07:00
{
2019-08-23 11:56:54 -07:00
NOT_IMPL;
}
2022-11-03 10:58:24 -07:00
void GLTexture::Blt(ImageData* imageData, int x, int y)
{
if (mImageData != NULL)
{
for (int row = 0; row < imageData->mHeight; row++)
{
memcpy(mImageData->mBits + (y + row) * mImageData->mWidth + x,
imageData->mBits + row * imageData->mWidth, imageData->mWidth * 4);
}
}
else
{
glBindTexture(GL_TEXTURE_2D, mGLTexture);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, imageData->mWidth, imageData->mHeight, GL_RGBA, GL_UNSIGNED_BYTE, imageData->mBits);
}
}
2019-08-23 11:56:54 -07:00
2022-11-03 10:58:24 -07:00
///
2019-08-23 11:56:54 -07:00
2022-11-03 10:58:24 -07:00
GLDrawBatch::GLDrawBatch() : DrawBatch()
{
2019-08-23 11:56:54 -07:00
}
GLDrawBatch::~GLDrawBatch()
{
}
extern int gBFDrawBatchCount;
2022-11-03 10:58:24 -07:00
struct GLVertex3D
{
float x, y, z;
float u, v;
uint32 color;
};
void GLDrawBatch::Render(RenderDevice* renderDevice, RenderWindow* renderWindow)
2019-08-23 11:56:54 -07:00
{
if (mIdxIdx == 0)
return;
gBFDrawBatchCount++;
2022-11-03 10:58:24 -07:00
GLRenderDevice* glRenderDevice = (GLRenderDevice*) gBFApp->mRenderDevice;
GLShader* curShader = (GLShader*)mRenderState->mShader;
2019-08-23 11:56:54 -07:00
2022-11-03 10:58:24 -07:00
if (glRenderDevice->mGLVAO == 0)
2019-08-23 11:56:54 -07:00
{
2022-11-03 10:58:24 -07:00
bf_glGenVertexArrays(1, &glRenderDevice->mGLVAO);
bf_glBindVertexArray(glRenderDevice->mGLVAO);
bf_glGenBuffers(1, &glRenderDevice->mGLVertexBuffer);
2019-08-23 11:56:54 -07:00
bf_glGenBuffers(1, &glRenderDevice->mGLIndexBuffer);
2022-11-03 10:58:24 -07:00
}
auto glVertices = (GLVertex3D*)mVertices;
2019-08-23 11:56:54 -07:00
bf_glBindBuffer(GL_ARRAY_BUFFER, glRenderDevice->mGLVertexBuffer);
2022-11-03 10:58:24 -07:00
bf_glBufferData(GL_ARRAY_BUFFER, mVtxIdx * sizeof(GLVertex3D), mVertices, GL_STREAM_DRAW);
bf_glEnableVertexAttribArray(curShader->mAttribPosition);
bf_glVertexAttribPointer(curShader->mAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLVertex3D), (void*)offsetof(GLVertex3D, x));
bf_glEnableVertexAttribArray(curShader->mAttribTexCoord0);
bf_glVertexAttribPointer(curShader->mAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex3D), (void*)offsetof(GLVertex3D, u));
bf_glEnableVertexAttribArray(curShader->mAttribColor);
bf_glVertexAttribPointer(curShader->mAttribColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GLVertex3D), (void*)offsetof(GLVertex3D, color));
if (mRenderState != renderDevice->mPhysRenderState)
renderDevice->PhysSetRenderState(mRenderState);
2019-08-23 11:56:54 -07:00
bf_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glRenderDevice->mGLIndexBuffer);
bf_glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIdxIdx * sizeof(int16), mIndices, GL_STREAM_DRAW);
bf_glDrawElements(GL_TRIANGLES, mIdxIdx, GL_UNSIGNED_SHORT, NULL);
2022-11-03 10:58:24 -07:00
2019-08-23 11:56:54 -07:00
bf_glBufferData(GL_ELEMENT_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW);
bf_glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW);
}
GLDrawLayer::GLDrawLayer()
{
}
GLDrawLayer::~GLDrawLayer()
{
}
DrawBatch* GLDrawLayer::CreateDrawBatch()
{
return new GLDrawBatch();
}
2022-11-03 10:58:24 -07:00
RenderCmd* GLDrawLayer::CreateSetTextureCmd(int textureIdx, Texture* texture)
{
GLSetTextureCmd* setTextureCmd = AllocRenderCmd<GLSetTextureCmd>();
setTextureCmd->mTextureIdx = textureIdx;
setTextureCmd->mTexture = texture;
return setTextureCmd;
}
2019-08-23 11:56:54 -07:00
2022-11-03 10:58:24 -07:00
void GLDrawLayer::SetShaderConstantData(int usageIdx, int slotIdx, void* constData, int size)
{
2019-08-23 11:56:54 -07:00
}
void GLRenderDevice::PhysSetRenderWindow(RenderWindow* renderWindow)
{
mCurRenderTarget = renderWindow;
mPhysRenderWindow = renderWindow;
((GLRenderWindow*)renderWindow)->PhysSetAsTarget();
}
void GLRenderDevice::PhysSetRenderTarget(Texture* renderTarget)
{
mCurRenderTarget = renderTarget;
2022-11-03 10:58:24 -07:00
renderTarget->PhysSetAsTarget();
2019-08-23 11:56:54 -07:00
}
2022-11-03 10:58:24 -07:00
2019-08-23 11:56:54 -07:00
///
template <typename T>
static void BFGetGLProc(T& proc, const char* name)
{
proc = (T)SDL_GL_GetProcAddress(name);
}
2022-11-03 10:58:24 -07:00
#define BF_GET_GLPROC(name) BFGetGLProc(bf_##name, #name)
void GL_DebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
{
NOP;
}
2019-08-23 11:56:54 -07:00
GLRenderWindow::GLRenderWindow(GLRenderDevice* renderDevice, SDL_Window* sdlWindow)
2022-11-03 10:58:24 -07:00
{
2019-08-23 11:56:54 -07:00
if (bf_glGenBuffers == NULL)
{
2022-11-03 10:58:24 -07:00
BF_GET_GLPROC(glDebugMessageCallback);
BF_GET_GLPROC(glActiveTexture);
BF_GET_GLPROC(glGenVertexArrays);
BF_GET_GLPROC(glBindVertexArray);
2019-08-23 11:56:54 -07:00
BF_GET_GLPROC(glGenBuffers);
BF_GET_GLPROC(glBindBuffer);
BF_GET_GLPROC(glBufferData);
BF_GET_GLPROC(glDeleteBuffers);
BF_GET_GLPROC(glMapBuffer);
BF_GET_GLPROC(glUnmapBuffer);
BF_GET_GLPROC(glGetBufferParameteriv);
BF_GET_GLPROC(glColorPointer);
BF_GET_GLPROC(glDrawArrays);
BF_GET_GLPROC(glEdgeFlagPointer);
BF_GET_GLPROC(glGetPointerv);
BF_GET_GLPROC(glIndexPointer);
BF_GET_GLPROC(glNormalPointer);
BF_GET_GLPROC(glTexCoordPointer);
BF_GET_GLPROC(glVertexPointer);
BF_GET_GLPROC(glDrawElements);
BF_GET_GLPROC(glVertexAttribPointer);
BF_GET_GLPROC(glAttachShader);
BF_GET_GLPROC(glBindAttribLocation);
BF_GET_GLPROC(glCompileShader);
BF_GET_GLPROC(glCreateProgram);
BF_GET_GLPROC(glCreateShader);
BF_GET_GLPROC(glDeleteProgram);
BF_GET_GLPROC(glDeleteShader);
BF_GET_GLPROC(glDetachShader);
BF_GET_GLPROC(glDisableVertexAttribArray);
BF_GET_GLPROC(glEnableVertexAttribArray);
BF_GET_GLPROC(glGetActiveAttrib);
BF_GET_GLPROC(glGetActiveUniform);
BF_GET_GLPROC(glGetAttachedShaders);
BF_GET_GLPROC(glGetAttribLocation);
BF_GET_GLPROC(glGetProgramiv);
BF_GET_GLPROC(glGetProgramInfoLog);
BF_GET_GLPROC(glGetShaderiv);
BF_GET_GLPROC(glGetShaderInfoLog);
BF_GET_GLPROC(glGetShaderSource);
BF_GET_GLPROC(glGetUniformLocation);
BF_GET_GLPROC(glGetUniformfv);
BF_GET_GLPROC(glGetUniformiv);
BF_GET_GLPROC(glGetVertexAttribfv);
BF_GET_GLPROC(glGetVertexAttribiv);
BF_GET_GLPROC(glGetVertexAttribPointerv);
BF_GET_GLPROC(glIsProgram);
BF_GET_GLPROC(glIsShader);
BF_GET_GLPROC(glLinkProgram);
BF_GET_GLPROC(glShaderSource);
BF_GET_GLPROC(glUseProgram);
BF_GET_GLPROC(glUniform1f);
BF_GET_GLPROC(glUniform2f);
BF_GET_GLPROC(glUniform3f);
2022-11-03 10:58:24 -07:00
BF_GET_GLPROC(glUniform4f);
2019-08-23 11:56:54 -07:00
BF_GET_GLPROC(glUniformMatrix4fv);
BF_GET_GLPROC(glGetObjectParameterivARB);
BF_GET_GLPROC(glCompressedTexImage2D);
BF_GET_GLPROC(glClientActiveTexture);
2022-11-03 10:58:24 -07:00
2019-08-23 11:56:54 -07:00
#if !defined BF_PLATFORM_OPENGL_ES2
BF_GET_GLPROC(glGetVertexAttribdv);
#endif
}
mSDLWindow = sdlWindow;
2022-11-03 10:58:24 -07:00
mRenderDevice = renderDevice;
2019-08-23 11:56:54 -07:00
Resized();
2022-11-03 10:58:24 -07:00
//bf_glDebugMessageCallback(GL_DebugCallback, NULL);
2019-08-23 11:56:54 -07:00
}
GLRenderWindow::~GLRenderWindow()
2022-11-03 10:58:24 -07:00
{
2019-08-23 11:56:54 -07:00
}
void GLRenderWindow::PhysSetAsTarget()
{
GLfloat matrix[4][4];
CreateOrthographicOffCenter(0.0f, (float)mWidth, (float)mHeight, 0.0f, -100.0f, 100.0f, matrix);
glViewport(0, 0, (GLsizei)mWidth, (GLsizei)mHeight);
2022-11-03 10:58:24 -07:00
mHasBeenDrawnTo = true;
2019-08-23 11:56:54 -07:00
}
void GLRenderWindow::SetAsTarget()
{
//TODO: Handle this more elegantly when we actually handle draw layers properly...
//if (mRenderDevice->mCurRenderTarget != NULL)
//mRenderDevice->mCurDrawLayer->Flush();
mHasBeenTargeted = true;
2022-11-03 10:58:24 -07:00
mRenderDevice->mCurRenderTarget = this;
2019-08-23 11:56:54 -07:00
}
void GLRenderWindow::Resized()
{
mRenderDevice->mResizeCount++;
mResizeNum = mRenderDevice->mResizeCount;
SDL_GetWindowSize(mSDLWindow, &mWidth, &mHeight);
//NOT_IMPL;
/*if (mGLSwapChain != NULL)
{
mGLRenderTargetView->Release();
mGLBackBuffer->Release();
GLCHECK(mGLSwapChain->ResizeBuffers(1, mWidth, mHeight, GLGI_FORMAT_R8G8B8A8_UNORM, 0));
2022-11-03 10:58:24 -07:00
GLCHECK(mGLSwapChain->GetBuffer(0, __uuidof(IGL10Texture2D), (LPVOID*)&mGLBackBuffer));
GLCHECK(mRenderDevice->mGLDevice->CreateRenderTargetView(mGLBackBuffer, NULL, &mGLRenderTargetView));
2019-08-23 11:56:54 -07:00
}*/
}
void GLRenderWindow::Present()
2022-11-03 10:58:24 -07:00
{
SDL_GL_SwapWindow(mSDLWindow);
//GLCHECK(mGLSwapChain->Present((mWindow->mFlags & BFWINDOW_VSYNC) ? 1 : 0, 0));
2019-08-23 11:56:54 -07:00
}
void GLRenderWindow::CopyBitsTo(uint32* dest, int width, int height)
2022-11-03 10:58:24 -07:00
{
2019-08-23 11:56:54 -07:00
mCurDrawLayer->Flush();
NOT_IMPL;
/*GL10_TEXTURE2D_DESC texDesc;
texDesc.ArraySize = 1;
texDesc.BindFlags = 0;
texDesc.CPUAccessFlags = 0;
texDesc.Format = GLGI_FORMAT_R8G8B8A8_UNORM;
texDesc.Width = width;
texDesc.Height = height;
texDesc.MipLevels = 1;
texDesc.MiscFlags = 0;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = GL10_USAGE_STAGING;
texDesc.CPUAccessFlags = GL10_CPU_ACCESS_READ;
IGL10Texture2D *texture;
GLCHECK(mRenderDevice->mGLDevice->CreateTexture2D(&texDesc, 0, &texture));
mRenderDevice->mGLDevice->CopyResource(texture, mGLBackBuffer);
GL10_MAPPED_TEXTURE2D mapTex;
GLCHECK(texture->Map(GL10CalcSubresource(0, 0, 1), GL10_MAP_READ, 0, &mapTex));
uint8* srcPtr = (uint8*) mapTex.pData;
uint8* destPtr = (uint8*) dest;
for (int y = 0; y < height; y++)
{
memcpy(destPtr, srcPtr, width*sizeof(uint32));
srcPtr += mapTex.RowPitch;
destPtr += width * 4;
}
texture->Unmap(0);
texture->Release();*/
}
///
GLRenderDevice::GLRenderDevice()
2022-11-03 10:58:24 -07:00
{
2019-08-23 11:56:54 -07:00
//mGLDevice = NULL;
2022-11-03 10:58:24 -07:00
mCurShader = NULL;
mGLVAO = 0;
2019-08-23 11:56:54 -07:00
mGLVertexBuffer = 0;
2022-11-03 10:58:24 -07:00
mGLIndexBuffer = 0;
2019-08-23 11:56:54 -07:00
mBlankTexture = 0;
mFreeBatchHead = NULL;
}
GLRenderDevice::~GLRenderDevice()
{
}
bool GLRenderDevice::Init(BFApp* app)
{
2022-11-03 10:58:24 -07:00
SdlBFApp* winApp = (SdlBFApp*) app;
//RenderState* glRenderState;
if (mDefaultRenderState == NULL)
{
auto dxRenderState = (RenderState*)CreateRenderState(NULL);
mDefaultRenderState = dxRenderState;
mDefaultRenderState->mDepthFunc = DepthFunc_Less;
mDefaultRenderState->mWriteDepthBuffer = true;
mPhysRenderState = mDefaultRenderState;
}
else
{
//glRenderState = (DXRenderState*)mDefaultRenderState;
//glRenderState->ReinitNative();
}
///
2019-08-23 11:56:54 -07:00
////Use GL10_CREATE_DEVICE_DEBUG for PIX
//GLCHECK(GL10CreateDevice(NULL, GL10_DRIVER_TYPE_HARDWARE, NULL, GL10_CREATE_DEVICE_DEBUG, GL10_SDK_VERSION, &mGLDevice));
////GLCHECK(GL10CreateDevice(NULL, GL10_DRIVER_TYPE_HARDWARE, NULL, 0, GL10_SDK_VERSION, &mGLDevice));
//IGLGIDevice* pGLGIDevice = NULL;
//GLCHECK(mGLDevice->QueryInterface(__uuidof(IGLGIDevice), reinterpret_cast<void**>(&pGLGIDevice)));
//IGLGIAdapter* pGLGIAdapter = NULL;
//GLCHECK(pGLGIDevice->GetParent(__uuidof(IGLGIAdapter), reinterpret_cast<void**>(&pGLGIAdapter)));
//IGLGIFactory* pGLGIFactory = NULL;
//GLCHECK(pGLGIAdapter->GetParent(__uuidof(IGLGIFactory), reinterpret_cast<void**>(&mGLGIFactory)));
2022-11-03 10:58:24 -07:00
////set rasterizer
2019-08-23 11:56:54 -07:00
//GL10_RASTERIZER_DESC rasterizerState;
//rasterizerState.CullMode = GL10_CULL_NONE;
//rasterizerState.FillMode = GL10_FILL_SOLID;
//rasterizerState.FrontCounterClockwise = true;
// rasterizerState.DepthBias = false;
// rasterizerState.DepthBiasClamp = 0;
// rasterizerState.SlopeScaledDepthBias = 0;
// rasterizerState.DepthClipEnable = false;
// rasterizerState.ScissorEnable = true;
// //TODO:rasterizerState.MultisampleEnable = false;
//rasterizerState.MultisampleEnable = true;
// rasterizerState.AntialiasedLineEnable = true;
//
2022-11-03 10:58:24 -07:00
//mGLDevice->CreateRasterizerState( &rasterizerState, &mGLRasterizerStateClipped);
2019-08-23 11:56:54 -07:00
//
//rasterizerState.ScissorEnable = false;
2022-11-03 10:58:24 -07:00
//mGLDevice->CreateRasterizerState( &rasterizerState, &mGLRasterizerStateUnclipped);
2019-08-23 11:56:54 -07:00
//mGLDevice->RSSetState(mGLRasterizerStateUnclipped);
//
//IGL10BlendState* g_pBlendState = NULL;
//GL10_BLEND_DESC BlendState;
//ZeroMemory(&BlendState, sizeof(GL10_BLEND_DESC));
//BlendState.BlendEnable[0] = TRUE;
////BlendState.SrcBlend = GL10_BLEND_SRC_ALPHA;
//BlendState.SrcBlend = GL10_BLEND_ONE;
//BlendState.DestBlend = GL10_BLEND_INV_SRC_ALPHA;
//BlendState.BlendOp = GL10_BLEND_OP_ADD;
//BlendState.SrcBlendAlpha = GL10_BLEND_ONE;
//BlendState.DestBlendAlpha = GL10_BLEND_ONE;
//BlendState.BlendOpAlpha = GL10_BLEND_OP_ADD;
//BlendState.RenderTargetWriteMask[0] = GL10_COLOR_WRITE_ENABLE_ALL;
//mGLDevice->CreateBlendState(&BlendState, &mGLNormalBlendState);
//BlendState.DestBlend = GL10_BLEND_ONE;
//mGLDevice->CreateBlendState(&BlendState, &mGLAdditiveBlendState);
//PhysSetAdditive(false);
return true;
}
void GLRenderDevice::FrameStart()
2022-11-03 10:58:24 -07:00
{
2019-08-23 11:56:54 -07:00
mCurRenderTarget = NULL;
mPhysRenderWindow = NULL;
2022-11-03 10:58:24 -07:00
for (auto aRenderWindow : mRenderWindowList)
2019-08-23 11:56:54 -07:00
{
2022-11-03 10:58:24 -07:00
aRenderWindow->mHasBeenDrawnTo = false;
aRenderWindow->mHasBeenTargeted = false;
}
2019-08-23 11:56:54 -07:00
}
void GLRenderDevice::FrameEnd()
2022-11-03 10:58:24 -07:00
{
for (auto aRenderWindow : mRenderWindowList)
2019-08-23 11:56:54 -07:00
{
if (aRenderWindow->mHasBeenTargeted)
{
2022-11-03 10:58:24 -07:00
PhysSetRenderWindow(aRenderWindow);
PhysSetRenderState(mDefaultRenderState);
2019-08-23 11:56:54 -07:00
2022-11-03 10:58:24 -07:00
for (auto drawLayer : aRenderWindow->mDrawLayerList)
2019-08-23 11:56:54 -07:00
{
drawLayer->Flush();
}
aRenderWindow->Present();
}
}
}
2022-11-03 10:58:24 -07:00
Texture* GLRenderDevice::LoadTexture(ImageData* imageData, int flags)
2019-08-23 11:56:54 -07:00
{
2022-11-03 10:58:24 -07:00
imageData->mIsAdditive = (flags & TextureFlag_Additive) != 0;
2019-08-23 11:56:54 -07:00
imageData->PremultiplyAlpha();
//int w = power_of_two(imageData->mWidth);
//int h = power_of_two(imageData->mHeight);
GLTexture* glTexture = new GLTexture();
2022-11-03 10:58:24 -07:00
glTexture->mRenderDevice = this;
2019-08-23 11:56:54 -07:00
glTexture->mWidth = imageData->mWidth;
glTexture->mHeight = imageData->mHeight;
2022-11-03 10:58:24 -07:00
glTexture->mImageData = imageData;
imageData->AddRef();
2019-08-23 11:56:54 -07:00
return glTexture;
}
2022-11-03 10:58:24 -07:00
Shader* GLRenderDevice::LoadShader(const StringImpl& fileName, VertexDefinition* vertexDefinition)
2019-08-23 11:56:54 -07:00
{
GLShader* glShader = new GLShader();
2022-11-03 10:58:24 -07:00
glShader->mVertexSize = sizeof(GLVertex3D);
2019-08-23 11:56:54 -07:00
glShader->mGLVertexShader = bf_glCreateShader(GL_VERTEX_SHADER);
glShader->mGLFragmentShader = bf_glCreateShader(GL_FRAGMENT_SHADER);
2022-11-03 10:58:24 -07:00
2019-08-23 11:56:54 -07:00
GLint vertProgramLen = 0;
GLint fragProgramLen = 0;
2022-11-03 10:58:24 -07:00
2019-08-23 11:56:54 -07:00
#ifdef BF_PLATFORM_OPENGL_ES2
2022-11-03 10:58:24 -07:00
GLchar* vertProgram = (GLchar*)LoadBinaryData(fileName + "_es.vert", &vertProgramLen);
GLchar* fragProgram = (GLchar*)LoadBinaryData(fileName + "_es.frag", &fragProgramLen);
2019-08-23 11:56:54 -07:00
#else
2022-11-03 10:58:24 -07:00
GLchar* vertProgram = (GLchar*)LoadBinaryData(fileName + ".vert", &vertProgramLen);
GLchar* fragProgram = (GLchar*)LoadBinaryData(fileName + ".frag", &fragProgramLen);
2019-08-23 11:56:54 -07:00
#endif
if ((vertProgram == NULL) || (fragProgram == NULL))
{
delete vertProgram;
delete fragProgram;
return NULL;
}
int infoLogLen = 0;
char infoLog[2048];
2022-11-03 10:58:24 -07:00
2019-08-23 11:56:54 -07:00
bf_glShaderSource(glShader->mGLVertexShader, 1, (const GLchar**)&vertProgram, &vertProgramLen);
bf_glCompileShader(glShader->mGLVertexShader);
bf_glGetShaderInfoLog(glShader->mGLVertexShader, 2048, &infoLogLen, infoLog);
GLint compiled = 0;
2022-11-03 10:58:24 -07:00
2019-08-23 11:56:54 -07:00
//bf_glGetObjectParameterivARB(glShader->mGLVertexShader, GL_COMPILE_STATUS, &compiled);
bf_glGetShaderiv(glShader->mGLVertexShader, GL_COMPILE_STATUS, &compiled);
if (!compiled)
BF_FATAL(StrFormat("Shader error: %s", infoLog).c_str());
2022-11-03 10:58:24 -07:00
2019-08-23 11:56:54 -07:00
bf_glShaderSource(glShader->mGLFragmentShader, 1, (const GLchar**)&fragProgram, &fragProgramLen);
bf_glCompileShader(glShader->mGLFragmentShader);
bf_glGetShaderInfoLog(glShader->mGLFragmentShader, 2048, &infoLogLen, infoLog);
compiled = 0;
//bf_glGetObjectParameterivARB(glShader->mGLFragmentShader, GL_COMPILE_STATUS, &compiled);
bf_glGetShaderiv(glShader->mGLFragmentShader, GL_COMPILE_STATUS, &compiled);
if (!compiled)
BF_FATAL(StrFormat("Shader error: %s", infoLog).c_str());
glShader->mGLProgram = bf_glCreateProgram();
bf_glAttachShader(glShader->mGLProgram, glShader->mGLVertexShader);
bf_glAttachShader(glShader->mGLProgram, glShader->mGLFragmentShader);
bf_glLinkProgram(glShader->mGLProgram);
2022-11-03 10:58:24 -07:00
glShader->mAttribPosition = bf_glGetAttribLocation(glShader->mGLProgram, "position");
glShader->mAttribTexCoord0 = bf_glGetAttribLocation(glShader->mGLProgram, "texCoord0");
glShader->mAttribColor = bf_glGetAttribLocation(glShader->mGLProgram, "color");
glShader->mAttribTex0 = bf_glGetUniformLocation(glShader->mGLProgram, "tex");
glShader->mAttribTex1 = bf_glGetUniformLocation(glShader->mGLProgram, "tex2");
2019-08-23 11:56:54 -07:00
return glShader;
}
2022-11-03 10:58:24 -07:00
void GLRenderDevice::PhysSetRenderState(RenderState* renderState)
2019-08-23 11:56:54 -07:00
{
2022-11-03 10:58:24 -07:00
mCurShader = (GLShader*)renderState->mShader;
if (mCurShader != NULL)
{
bf_glUseProgram(mCurShader->mGLProgram);
2019-08-23 11:56:54 -07:00
2022-11-03 10:58:24 -07:00
GLRenderDevice* aRenderDevice = (GLRenderDevice*)gBFApp->mRenderDevice;
//TODO: Cache more
GLfloat matrix[4][4];
CreateOrthographicOffCenter(0.0f, (float)mPhysRenderWindow->mWidth, (float)mPhysRenderWindow->mHeight, 0.0f, -100.0f, 100.0f, matrix);
GLint matrixLoc = bf_glGetUniformLocation(mCurShader->mGLProgram, "screenMatrix");
//BF_ASSERT(matrixLoc >= 0);
if (matrixLoc >= 0)
bf_glUniformMatrix4fv(matrixLoc, 1, false, (float*)matrix);
}
if (renderState->mClipped)
{
glEnable(GL_SCISSOR_TEST);
glScissor((GLsizei)renderState->mClipRect.mX,
mPhysRenderWindow->mHeight - (GLsizei)renderState->mClipRect.mY - (GLsizei)renderState->mClipRect.mHeight,
(GLsizei)renderState->mClipRect.mWidth, (GLsizei)renderState->mClipRect.mHeight);
}
2019-08-23 11:56:54 -07:00
else
2022-11-03 10:58:24 -07:00
{
glDisable(GL_SCISSOR_TEST);
}
mPhysRenderState = renderState;
2019-08-23 11:56:54 -07:00
}
2022-11-03 10:58:24 -07:00
Texture* GLRenderDevice::CreateRenderTarget(int width, int height, bool destAlpha)
2019-08-23 11:56:54 -07:00
{
NOT_IMPL;
}
2022-11-03 10:58:24 -07:00
void GLRenderDevice::SetRenderState(RenderState* renderState)
2019-08-23 11:56:54 -07:00
{
2022-11-03 10:58:24 -07:00
mCurRenderState = renderState;
2019-08-23 11:56:54 -07:00
}
2022-11-03 10:58:24 -07:00
void GLSetTextureCmd::Render(RenderDevice* renderDevice, RenderWindow* renderWindow)
2019-08-23 11:56:54 -07:00
{
2022-11-03 10:58:24 -07:00
/*#ifdef BF_PLATFORM_OPENGL_ES2
//bf_glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, ((GLTexture*)mTexture)->mGLTexture);
glUniform1i(curShader->mAttribTex0, 0);
2019-08-23 11:56:54 -07:00
2022-11-03 10:58:24 -07:00
//bf_glClientActiveTexture(GL_TEXTURE1);
2019-08-23 11:56:54 -07:00
2022-11-03 10:58:24 -07:00
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, ((GLTexture*)mTexture)->mGLTexture2);
glUniform1i(curShader->mAttribTex1, 1);
//glEnable(GL_TEXTURE_2D);
#else
glActiveTexture(GL_TEXTURE0 + mTextureIdx);
glBindTexture(GL_TEXTURE_2D, ((GLTexture*)mTexture)->mGLTexture);
#endif*/
auto glTexture = (GLTexture*)mTexture;
auto glRenderDevice = (GLRenderDevice*)renderDevice;
if (glRenderDevice->mBlankTexture == 0)
{
glGenTextures(1, &glRenderDevice->mBlankTexture);
glBindTexture(GL_TEXTURE_2D, glRenderDevice->mBlankTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/*if (bf_glCompressedTexImage2D != NULL)
{
uint64 hwData = 0;
bf_glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 4, 4, 0,
sizeof(hwData), (uint8*)&hwData);
}
else*/
{
uint16 color = 0;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0,
GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, &color);
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
}
if (glTexture->mImageData != NULL)
{
glTexture->mGLTexture2 = glRenderDevice->mBlankTexture;
int texCount = 1;
//texCount = (imageData->mHWBitsType == HWBITS_PVRTC_2X4BPPV1) ? 2 : 1;
for (int texNum = 0; texNum < 2/*texCount*/; texNum++)
{
GLuint glTextureID;
glGenTextures(1, &glTextureID);
glBindTexture(GL_TEXTURE_2D, glTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//if (imageData->mHWBits != NULL)
//{
// int internalFormat = (imageData->mHWBitsType == HWBITS_PVRTC_2BPPV1) ?
// GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG :
// GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
// int texSize = imageData->mHWBitsLength / texCount;
// bf_glCompressedTexImage2D(GL_TEXTURE_2D, 0, internalFormat, imageData->mWidth, imageData->mHeight, 0,
// texSize, (uint8*)imageData->mHWBits /*+ (texNum * texSize)*/);
//}
//else
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glTexture->mImageData->mWidth, glTexture->mImageData->mHeight, 0,
GL_RGBA, GL_UNSIGNED_BYTE, glTexture->mImageData->mBits);
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
if (texNum == 0)
glTexture->mGLTexture = glTextureID;
else
glTexture->mGLTexture2 = glTextureID;
}
glTexture->mImageData->Deref();
glTexture->mImageData = NULL;
}
bf_glActiveTexture(GL_TEXTURE0 + mTextureIdx);
//glUniform1i(curShader->mAttribTex0, 0);
glBindTexture(GL_TEXTURE_2D, glTexture->mGLTexture);
2019-08-23 11:56:54 -07:00
}