mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-23 01:21:57 -05:00
Reuse _GLShared.h in OpenGL2 backend
This commit is contained in:
parent
7a32b65d19
commit
542a6ff65d
4 changed files with 68 additions and 334 deletions
|
@ -152,7 +152,7 @@ Thus it is **NOT SAFE** to allocate a string on the stack. */
|
|||
#ifndef CC_BUILD_MANUAL
|
||||
#if defined _WIN32
|
||||
#define CC_BUILD_WIN
|
||||
#define CC_BUILD_GL
|
||||
#define CC_BUILD_D3D9
|
||||
#define CC_BUILD_WINGUI
|
||||
#define CC_BUILD_WININET
|
||||
#define CC_BUILD_WINMM
|
||||
|
|
|
@ -53,6 +53,7 @@ typedef void GLvoid;
|
|||
#define GL_FLOAT 0x1406
|
||||
#define GL_RGBA 0x1908
|
||||
#define GL_BGRA_EXT 0x80E1
|
||||
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
|
||||
|
||||
#define GL_FOG 0x0B60
|
||||
#define GL_FOG_DENSITY 0x0B62
|
||||
|
@ -95,11 +96,10 @@ typedef void GLvoid;
|
|||
#define GL_TEXTURE_COORD_ARRAY 0x8078
|
||||
|
||||
/* Not present in gl.h on Windows (only up to OpenGL 1.1) */
|
||||
#define _GL_ARRAY_BUFFER 0x8892
|
||||
#define _GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define _GL_STATIC_DRAW 0x88E4
|
||||
#define _GL_DYNAMIC_DRAW 0x88E8
|
||||
#define _GL_TEXTURE_MAX_LEVEL 0x813D
|
||||
#define GL_ARRAY_BUFFER 0x8892
|
||||
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define GL_STATIC_DRAW 0x88E4
|
||||
#define GL_DYNAMIC_DRAW 0x88E8
|
||||
|
||||
GLAPI void APIENTRY glAlphaFunc(GLenum func, GLfloat ref);
|
||||
GLAPI void APIENTRY glBindTexture(GLenum target, GLuint texture);
|
||||
|
@ -180,13 +180,13 @@ static GLuint GL_GenAndBind(GLenum target) {
|
|||
}
|
||||
|
||||
GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) {
|
||||
GLuint id = GL_GenAndBind(_GL_ELEMENT_ARRAY_BUFFER);
|
||||
GLuint id = GL_GenAndBind(GL_ELEMENT_ARRAY_BUFFER);
|
||||
cc_uint32 size = indicesCount * 2;
|
||||
_glBufferData(_GL_ELEMENT_ARRAY_BUFFER, size, indices, _GL_STATIC_DRAW);
|
||||
_glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, indices, GL_STATIC_DRAW);
|
||||
return id;
|
||||
}
|
||||
|
||||
void Gfx_BindIb(GfxResourceID ib) { _glBindBuffer(_GL_ELEMENT_ARRAY_BUFFER, (GLuint)ib); }
|
||||
void Gfx_BindIb(GfxResourceID ib) { _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)ib); }
|
||||
|
||||
void Gfx_DeleteIb(GfxResourceID* ib) {
|
||||
GLuint id = (GLuint)(*ib);
|
||||
|
@ -206,10 +206,10 @@ void Gfx_DeleteIb(GfxResourceID* ib) { }
|
|||
*#########################################################################################################################*/
|
||||
#ifndef CC_BUILD_GL11
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
return GL_GenAndBind(_GL_ARRAY_BUFFER);
|
||||
return GL_GenAndBind(GL_ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
void Gfx_BindVb(GfxResourceID vb) { _glBindBuffer(_GL_ARRAY_BUFFER, (GLuint)vb); }
|
||||
void Gfx_BindVb(GfxResourceID vb) { _glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); }
|
||||
|
||||
void Gfx_DeleteVb(GfxResourceID* vb) {
|
||||
GLuint id = (GLuint)(*vb);
|
||||
|
@ -223,7 +223,7 @@ void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
|||
}
|
||||
|
||||
void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
_glBufferData(_GL_ARRAY_BUFFER, tmpSize, tmpData, _GL_STATIC_DRAW);
|
||||
_glBufferData(GL_ARRAY_BUFFER, tmpSize, tmpData, GL_STATIC_DRAW);
|
||||
}
|
||||
#else
|
||||
static void UpdateDisplayList(GLuint list, void* vertices, VertexFormat fmt, int count);
|
||||
|
@ -267,9 +267,9 @@ GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
|||
cc_uint32 size;
|
||||
if (Gfx.LostContext) return 0;
|
||||
|
||||
id = GL_GenAndBind(_GL_ARRAY_BUFFER);
|
||||
id = GL_GenAndBind(GL_ARRAY_BUFFER);
|
||||
size = maxVertices * strideSizes[fmt];
|
||||
_glBufferData(_GL_ARRAY_BUFFER, size, NULL, _GL_DYNAMIC_DRAW);
|
||||
_glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -278,14 +278,14 @@ void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
|||
}
|
||||
|
||||
void Gfx_UnlockDynamicVb(GfxResourceID vb) {
|
||||
_glBindBuffer(_GL_ARRAY_BUFFER, (GLuint)vb);
|
||||
_glBufferSubData(_GL_ARRAY_BUFFER, 0, tmpSize, tmpData);
|
||||
_glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb);
|
||||
_glBufferSubData(GL_ARRAY_BUFFER, 0, tmpSize, tmpData);
|
||||
}
|
||||
|
||||
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||
cc_uint32 size = vCount * gfx_stride;
|
||||
_glBindBuffer(_GL_ARRAY_BUFFER, (GLuint)vb);
|
||||
_glBufferSubData(_GL_ARRAY_BUFFER, 0, size, vertices);
|
||||
_glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb);
|
||||
_glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices);
|
||||
}
|
||||
#else
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
|
@ -434,13 +434,13 @@ cc_bool Gfx_WarnIfNecessary(void) {
|
|||
*-------------------------------------------------------Compatibility-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#ifdef CC_BUILD_GL11
|
||||
static void GL_CheckSupport(void) { MakeIndices(gl_indices, GFX_MAX_INDICES); }
|
||||
static void GLBackend_Init(void) { MakeIndices(gl_indices, GFX_MAX_INDICES); }
|
||||
#else
|
||||
/* fake vertex buffer objects with client side pointers */
|
||||
typedef struct fake_buffer { cc_uint8* data; } fake_buffer;
|
||||
static fake_buffer* cur_ib;
|
||||
static fake_buffer* cur_vb;
|
||||
#define fake_GetBuffer(target) (target == _GL_ELEMENT_ARRAY_BUFFER ? &cur_ib : &cur_vb);
|
||||
#define fake_GetBuffer(target) (target == GL_ELEMENT_ARRAY_BUFFER ? &cur_ib : &cur_vb);
|
||||
|
||||
static void APIENTRY fake_glBindBuffer(GLenum target, GLuint src) {
|
||||
fake_buffer** buffer = fake_GetBuffer(target);
|
||||
|
|
|
@ -26,223 +26,10 @@
|
|||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
/* Not present in gl.h on Windows (only up to OpenGL 1.1) */
|
||||
#define _GL_ARRAY_BUFFER 0x8892
|
||||
#define _GL_ELEMENT_ARRAY_BUFFER 0x8893
|
||||
#define _GL_STATIC_DRAW 0x88E4
|
||||
#define _GL_DYNAMIC_DRAW 0x88E8
|
||||
#define _GL_TEXTURE_MAX_LEVEL 0x813D
|
||||
|
||||
#define _GL_FRAGMENT_SHADER 0x8B30
|
||||
#define _GL_VERTEX_SHADER 0x8B31
|
||||
#define _GL_COMPILE_STATUS 0x8B81
|
||||
#define _GL_LINK_STATUS 0x8B82
|
||||
#define _GL_INFO_LOG_LENGTH 0x8B84
|
||||
|
||||
#if defined CC_BUILD_WEB || defined CC_BUILD_ANDROID
|
||||
#define PIXEL_FORMAT GL_RGBA
|
||||
#else
|
||||
#define PIXEL_FORMAT 0x80E1 /* GL_BGRA_EXT */
|
||||
#endif
|
||||
|
||||
#if defined CC_BIG_ENDIAN
|
||||
/* Pixels are stored in memory as A,R,G,B but GL_UNSIGNED_BYTE will interpret as B,G,R,A */
|
||||
/* So use GL_UNSIGNED_INT_8_8_8_8_REV instead to remedy this */
|
||||
#define TRANSFER_FORMAT GL_UNSIGNED_INT_8_8_8_8_REV
|
||||
#else
|
||||
/* Pixels are stored in memory as B,G,R,A and GL_UNSIGNED_BYTE will interpret as B,G,R,A */
|
||||
/* So fine to just use GL_UNSIGNED_BYTE here */
|
||||
#define TRANSFER_FORMAT GL_UNSIGNED_BYTE
|
||||
#endif
|
||||
|
||||
typedef void (*GL_SetupVBFunc)(void);
|
||||
typedef void (*GL_SetupVBRangeFunc)(int startVertex);
|
||||
static GL_SetupVBFunc gfx_setupVBFunc;
|
||||
static GL_SetupVBRangeFunc gfx_setupVBRangeFunc;
|
||||
#include "_GLShared.h"
|
||||
/* Current format and size of vertices */
|
||||
static int gfx_stride, gfx_format = -1;
|
||||
|
||||
static void GL_UpdateVsync(void) {
|
||||
GLContext_SetFpsLimit(gfx_vsync, gfx_minFrameMs);
|
||||
}
|
||||
|
||||
static void GL_CheckSupport(void);
|
||||
void Gfx_Create(void) {
|
||||
GLContext_Create();
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Gfx.MaxTexWidth);
|
||||
Gfx.MaxTexHeight = Gfx.MaxTexWidth;
|
||||
Gfx.Created = true;
|
||||
|
||||
GL_CheckSupport();
|
||||
Gfx_RestoreState();
|
||||
GL_UpdateVsync();
|
||||
}
|
||||
|
||||
cc_bool Gfx_TryRestoreContext(void) {
|
||||
return GLContext_TryRestore();
|
||||
}
|
||||
|
||||
void Gfx_Free(void) {
|
||||
Gfx_FreeState();
|
||||
GLContext_Free();
|
||||
}
|
||||
|
||||
#define gl_Toggle(cap) if (enabled) { glEnable(cap); } else { glDisable(cap); }
|
||||
static void* tmpData;
|
||||
static int tmpSize;
|
||||
|
||||
static void* FastAllocTempMem(int size) {
|
||||
if (size > tmpSize) {
|
||||
Mem_Free(tmpData);
|
||||
tmpData = Mem_Alloc(size, 1, "Gfx_AllocTempMemory");
|
||||
}
|
||||
|
||||
tmpSize = size;
|
||||
return tmpData;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void Gfx_DoMipmaps(int x, int y, struct Bitmap* bmp, int rowWidth, cc_bool partial) {
|
||||
BitmapCol* prev = bmp->scan0;
|
||||
BitmapCol* cur;
|
||||
|
||||
int lvls = CalcMipmapsLevels(bmp->width, bmp->height);
|
||||
int lvl, width = bmp->width, height = bmp->height;
|
||||
|
||||
for (lvl = 1; lvl <= lvls; lvl++) {
|
||||
x /= 2; y /= 2;
|
||||
if (width > 1) width /= 2;
|
||||
if (height > 1) height /= 2;
|
||||
|
||||
cur = (BitmapCol*)Mem_Alloc(width * height, 4, "mipmaps");
|
||||
GenMipmaps(width, height, cur, prev, rowWidth);
|
||||
|
||||
if (partial) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, lvl, x, y, width, height, PIXEL_FORMAT, TRANSFER_FORMAT, cur);
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, lvl, GL_RGBA, width, height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, cur);
|
||||
}
|
||||
|
||||
if (prev != bmp->scan0) Mem_Free(prev);
|
||||
prev = cur;
|
||||
rowWidth = width;
|
||||
}
|
||||
if (prev != bmp->scan0) Mem_Free(prev);
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
GLuint texId;
|
||||
glGenTextures(1, &texId);
|
||||
glBindTexture(GL_TEXTURE_2D, texId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) {
|
||||
Logger_Abort("Textures must have power of two dimensions");
|
||||
}
|
||||
if (Gfx.LostContext) return 0;
|
||||
|
||||
if (mipmaps) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
|
||||
if (customMipmapsLevels) {
|
||||
int lvls = CalcMipmapsLevels(bmp->width, bmp->height);
|
||||
glTexParameteri(GL_TEXTURE_2D, _GL_TEXTURE_MAX_LEVEL, lvls);
|
||||
}
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmp->width, bmp->height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, bmp->scan0);
|
||||
|
||||
if (mipmaps) Gfx_DoMipmaps(0, 0, bmp, bmp->width, false);
|
||||
return texId;
|
||||
}
|
||||
|
||||
#define UPDATE_FAST_SIZE (64 * 64)
|
||||
static CC_NOINLINE void UpdateTextureSlow(int x, int y, struct Bitmap* part, int rowWidth) {
|
||||
BitmapCol buffer[UPDATE_FAST_SIZE];
|
||||
void* ptr = (void*)buffer;
|
||||
int count = part->width * part->height;
|
||||
|
||||
/* cannot allocate memory on the stack for very big updates */
|
||||
if (count > UPDATE_FAST_SIZE) {
|
||||
ptr = Mem_Alloc(count, 4, "Gfx_UpdateTexture temp");
|
||||
}
|
||||
|
||||
CopyTextureData(ptr, part->width << 2, part, rowWidth << 2);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, part->width, part->height, PIXEL_FORMAT, TRANSFER_FORMAT, ptr);
|
||||
if (count > UPDATE_FAST_SIZE) Mem_Free(ptr);
|
||||
}
|
||||
|
||||
void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) {
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)texId);
|
||||
/* TODO: Use GL_UNPACK_ROW_LENGTH for Desktop OpenGL */
|
||||
|
||||
if (part->width == rowWidth) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, part->width, part->height, PIXEL_FORMAT, TRANSFER_FORMAT, part->scan0);
|
||||
} else {
|
||||
UpdateTextureSlow(x, y, part, rowWidth);
|
||||
}
|
||||
if (mipmaps) Gfx_DoMipmaps(x, y, part, rowWidth, true);
|
||||
}
|
||||
|
||||
void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, struct Bitmap* part, cc_bool mipmaps) {
|
||||
Gfx_UpdateTexture(texId, x, y, part, part->width, mipmaps);
|
||||
}
|
||||
|
||||
void Gfx_BindTexture(GfxResourceID texId) {
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)texId);
|
||||
}
|
||||
|
||||
void Gfx_DeleteTexture(GfxResourceID* texId) {
|
||||
GLuint id = (GLuint)(*texId);
|
||||
if (!id) return;
|
||||
glDeleteTextures(1, &id);
|
||||
*texId = 0;
|
||||
}
|
||||
|
||||
void Gfx_EnableMipmaps(void) { }
|
||||
void Gfx_DisableMipmaps(void) { }
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------State management----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static PackedCol gfx_clearColor, gfx_fogColor;
|
||||
static float gfx_fogEnd = -1.0f, gfx_fogDensity = -1.0f;
|
||||
static int gfx_fogMode = -1;
|
||||
|
||||
void Gfx_SetFaceCulling(cc_bool enabled) { gl_Toggle(GL_CULL_FACE); }
|
||||
void Gfx_SetAlphaBlending(cc_bool enabled) { gl_Toggle(GL_BLEND); }
|
||||
void Gfx_SetAlphaArgBlend(cc_bool enabled) { }
|
||||
|
||||
static void GL_ClearCol(PackedCol col) {
|
||||
glClearColor(PackedCol_R(col) / 255.0f, PackedCol_G(col) / 255.0f,
|
||||
PackedCol_B(col) / 255.0f, PackedCol_A(col) / 255.0f);
|
||||
}
|
||||
void Gfx_ClearCol(PackedCol col) {
|
||||
if (col == gfx_clearColor) return;
|
||||
GL_ClearCol(col);
|
||||
gfx_clearColor = col;
|
||||
}
|
||||
|
||||
void Gfx_SetColWriteMask(cc_bool r, cc_bool g, cc_bool b, cc_bool a) {
|
||||
glColorMask(r, g, b, a);
|
||||
}
|
||||
|
||||
void Gfx_SetDepthWrite(cc_bool enabled) { glDepthMask(enabled); }
|
||||
void Gfx_SetDepthTest(cc_bool enabled) { gl_Toggle(GL_DEPTH_TEST); }
|
||||
|
||||
void Gfx_CalcOrthoMatrix(float width, float height, struct Matrix* matrix) {
|
||||
Matrix_Orthographic(matrix, 0.0f, width, 0.0f, height, ORTHO_NEAR, ORTHO_FAR);
|
||||
}
|
||||
void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zFar, struct Matrix* matrix) {
|
||||
float zNear = 0.1f;
|
||||
Matrix_PerspectiveFieldOfView(matrix, fov, aspect, zNear, zFar);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Index buffers-----------------------------------------------------*
|
||||
|
@ -255,13 +42,13 @@ static GLuint GL_GenAndBind(GLenum target) {
|
|||
}
|
||||
|
||||
GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) {
|
||||
GLuint id = GL_GenAndBind(_GL_ELEMENT_ARRAY_BUFFER);
|
||||
GLuint id = GL_GenAndBind(GL_ELEMENT_ARRAY_BUFFER);
|
||||
cc_uint32 size = indicesCount * 2;
|
||||
glBufferData(_GL_ELEMENT_ARRAY_BUFFER, size, indices, _GL_STATIC_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, indices, GL_STATIC_DRAW);
|
||||
return id;
|
||||
}
|
||||
|
||||
void Gfx_BindIb(GfxResourceID ib) { glBindBuffer(_GL_ELEMENT_ARRAY_BUFFER, (GLuint)ib); }
|
||||
void Gfx_BindIb(GfxResourceID ib) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)ib); }
|
||||
|
||||
void Gfx_DeleteIb(GfxResourceID* ib) {
|
||||
GLuint id = (GLuint)(*ib);
|
||||
|
@ -275,10 +62,10 @@ void Gfx_DeleteIb(GfxResourceID* ib) {
|
|||
*------------------------------------------------------Vertex buffers-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
return GL_GenAndBind(_GL_ARRAY_BUFFER);
|
||||
return GL_GenAndBind(GL_ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
void Gfx_BindVb(GfxResourceID vb) { glBindBuffer(_GL_ARRAY_BUFFER, (GLuint)vb); }
|
||||
void Gfx_BindVb(GfxResourceID vb) { glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); }
|
||||
|
||||
void Gfx_DeleteVb(GfxResourceID* vb) {
|
||||
GLuint id = (GLuint)(*vb);
|
||||
|
@ -292,7 +79,7 @@ void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
|||
}
|
||||
|
||||
void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
glBufferData(_GL_ARRAY_BUFFER, tmpSize, tmpData, _GL_STATIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, tmpSize, tmpData, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
|
||||
|
@ -304,9 +91,9 @@ GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
|||
cc_uint32 size;
|
||||
if (Gfx.LostContext) return 0;
|
||||
|
||||
id = GL_GenAndBind(_GL_ARRAY_BUFFER);
|
||||
id = GL_GenAndBind(GL_ARRAY_BUFFER);
|
||||
size = maxVertices * strideSizes[fmt];
|
||||
glBufferData(_GL_ARRAY_BUFFER, size, NULL, _GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -315,95 +102,17 @@ void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
|||
}
|
||||
|
||||
void Gfx_UnlockDynamicVb(GfxResourceID vb) {
|
||||
glBindBuffer(_GL_ARRAY_BUFFER, (GLuint)vb);
|
||||
glBufferSubData(_GL_ARRAY_BUFFER, 0, tmpSize, tmpData);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, tmpSize, tmpData);
|
||||
}
|
||||
|
||||
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||
cc_uint32 size = vCount * gfx_stride;
|
||||
glBindBuffer(_GL_ARRAY_BUFFER, (GLuint)vb);
|
||||
glBufferSubData(_GL_ARRAY_BUFFER, 0, size, vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------------Misc----------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static BitmapCol* GL_GetRow(struct Bitmap* bmp, int y) {
|
||||
/* OpenGL stores bitmap in bottom-up order, so flip order when saving */
|
||||
return Bitmap_GetRow(bmp, (bmp->height - 1) - y);
|
||||
}
|
||||
cc_result Gfx_TakeScreenshot(struct Stream* output) {
|
||||
struct Bitmap bmp;
|
||||
cc_result res;
|
||||
GLint vp[4];
|
||||
|
||||
glGetIntegerv(GL_VIEWPORT, vp); /* { x, y, width, height } */
|
||||
bmp.width = vp[2];
|
||||
bmp.height = vp[3];
|
||||
|
||||
bmp.scan0 = (BitmapCol*)Mem_TryAlloc(bmp.width * bmp.height, 4);
|
||||
if (!bmp.scan0) return ERR_OUT_OF_MEMORY;
|
||||
glReadPixels(0, 0, bmp.width, bmp.height, PIXEL_FORMAT, TRANSFER_FORMAT, bmp.scan0);
|
||||
|
||||
res = Png_Encode(&bmp, output, GL_GetRow, false);
|
||||
Mem_Free(bmp.scan0);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void AppendVRAMStats(cc_string* info) {
|
||||
static const cc_string memExt = String_FromConst("GL_NVX_gpu_memory_info");
|
||||
GLint totalKb, curKb;
|
||||
float total, cur;
|
||||
|
||||
/* NOTE: glGetString returns UTF8, but I just treat it as code page 437 */
|
||||
cc_string exts = String_FromReadonly((const char*)glGetString(GL_EXTENSIONS));
|
||||
if (!String_CaselessContains(&exts, &memExt)) return;
|
||||
|
||||
glGetIntegerv(0x9048, &totalKb);
|
||||
glGetIntegerv(0x9049, &curKb);
|
||||
if (totalKb <= 0 || curKb <= 0) return;
|
||||
|
||||
total = totalKb / 1024.0f; cur = curKb / 1024.0f;
|
||||
String_Format2(info, "Video memory: %f2 MB total, %f2 free\n", &total, &cur);
|
||||
}
|
||||
|
||||
void Gfx_GetApiInfo(cc_string* info) {
|
||||
GLint depthBits;
|
||||
int pointerSize = sizeof(void*) * 8;
|
||||
|
||||
glGetIntegerv(GL_DEPTH_BITS, &depthBits);
|
||||
String_Format1(info, "-- Using OpenGL (%i bit) --\n", &pointerSize);
|
||||
String_Format1(info, "Vendor: %c\n", glGetString(GL_VENDOR));
|
||||
String_Format1(info, "Renderer: %c\n", glGetString(GL_RENDERER));
|
||||
String_Format1(info, "GL version: %c\n", glGetString(GL_VERSION));
|
||||
AppendVRAMStats(info);
|
||||
String_Format2(info, "Max texture size: (%i, %i)\n", &Gfx.MaxTexWidth, &Gfx.MaxTexHeight);
|
||||
String_Format1(info, "Depth buffer bits: %i\n", &depthBits);
|
||||
GLContext_GetApiInfo(info);
|
||||
}
|
||||
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) {
|
||||
gfx_minFrameMs = minFrameMs;
|
||||
gfx_vsync = vsync;
|
||||
if (Gfx.Created) GL_UpdateVsync();
|
||||
}
|
||||
|
||||
void Gfx_BeginFrame(void) { frameStart = Stopwatch_Measure(); }
|
||||
void Gfx_Clear(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); }
|
||||
void Gfx_EndFrame(void) {
|
||||
if (!GLContext_SwapBuffers()) Gfx_LoseContext("GLContext lost");
|
||||
if (gfx_minFrameMs) LimitFPS();
|
||||
}
|
||||
|
||||
void Gfx_OnWindowResize(void) {
|
||||
GLContext_Update();
|
||||
/* In case GLContext_Update changes window bounds */
|
||||
/* TODO: Eliminate this nasty hack.. */
|
||||
Game_UpdateDimensions();
|
||||
glViewport(0, 0, Game.Width, Game.Height);
|
||||
}
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------OpenGL modern------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
|
@ -426,6 +135,9 @@ void Gfx_OnWindowResize(void) {
|
|||
static struct Matrix _view, _proj, _mvp;
|
||||
static cc_bool gfx_alphaTest, gfx_texTransform;
|
||||
static float _texX, _texY;
|
||||
static PackedCol gfx_fogColor;
|
||||
static float gfx_fogEnd = -1.0f, gfx_fogDensity = -1.0f;
|
||||
static int gfx_fogMode = -1;
|
||||
|
||||
/* shader programs (emulate fixed function) */
|
||||
static struct GLShader {
|
||||
|
@ -520,7 +232,7 @@ static GLint CompileShader(GLint shader, const cc_string* src) {
|
|||
|
||||
glShaderSource(shader, 1, &str, &len);
|
||||
glCompileShader(shader);
|
||||
glGetShaderiv(shader, _GL_COMPILE_STATUS, &temp);
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
@ -531,7 +243,7 @@ static void ShaderFailed(GLint shader) {
|
|||
if (!shader) Logger_Abort("Failed to create shader");
|
||||
|
||||
temp = 0;
|
||||
glGetShaderiv(shader, _GL_INFO_LOG_LENGTH, &temp);
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &temp);
|
||||
|
||||
if (temp > 1) {
|
||||
glGetShaderInfoLog(shader, 2047, NULL, logInfo);
|
||||
|
@ -547,14 +259,14 @@ static void CompileProgram(struct GLShader* shader) {
|
|||
GLuint vs, fs, program;
|
||||
GLint temp;
|
||||
|
||||
vs = glCreateShader(_GL_VERTEX_SHADER);
|
||||
vs = glCreateShader(GL_VERTEX_SHADER);
|
||||
if (!vs) { Platform_LogConst("Failed to create vertex shader"); return; }
|
||||
|
||||
String_InitArray(tmp, tmpBuffer);
|
||||
GenVertexShader(shader, &tmp);
|
||||
if (!CompileShader(vs, &tmp)) ShaderFailed(vs);
|
||||
|
||||
fs = glCreateShader(_GL_FRAGMENT_SHADER);
|
||||
fs = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!fs) { Platform_LogConst("Failed to create fragment shader"); glDeleteShader(vs); return; }
|
||||
|
||||
tmp.length = 0;
|
||||
|
@ -585,7 +297,7 @@ static void CompileProgram(struct GLShader* shader) {
|
|||
glBindAttribLocation(program, 2, "in_uv");
|
||||
|
||||
glLinkProgram(program);
|
||||
glGetProgramiv(program, _GL_LINK_STATUS, &temp);
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &temp);
|
||||
|
||||
if (temp) {
|
||||
glDetachShader(program, vs);
|
||||
|
@ -602,7 +314,7 @@ static void CompileProgram(struct GLShader* shader) {
|
|||
return;
|
||||
}
|
||||
temp = 0;
|
||||
glGetProgramiv(program, _GL_INFO_LOG_LENGTH, &temp);
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &temp);
|
||||
|
||||
if (temp > 0) {
|
||||
glGetProgramInfoLog(program, 2047, NULL, tmpBuffer);
|
||||
|
@ -674,6 +386,10 @@ static void SwitchProgram(void) {
|
|||
ReloadUniforms();
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------State management----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Gfx_SetFog(cc_bool enabled) { gfx_fogEnabled = enabled; SwitchProgram(); }
|
||||
void Gfx_SetFogCol(PackedCol col) {
|
||||
if (col == gfx_fogColor) return;
|
||||
|
@ -705,6 +421,10 @@ void Gfx_SetFogMode(FogFunc func) {
|
|||
void Gfx_SetTexturing(cc_bool enabled) { }
|
||||
void Gfx_SetAlphaTest(cc_bool enabled) { gfx_alphaTest = enabled; SwitchProgram(); }
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Matrices--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) {
|
||||
if (type == MATRIX_VIEW) _view = *matrix;
|
||||
if (type == MATRIX_PROJECTION) _proj = *matrix;
|
||||
|
@ -729,7 +449,11 @@ void Gfx_DisableTextureOffset(void) {
|
|||
SwitchProgram();
|
||||
}
|
||||
|
||||
static void GL_CheckSupport(void) {
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------State setup-------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void GLBackend_Init(void) {
|
||||
#ifndef CC_BUILD_GLES
|
||||
customMipmapsLevels = true;
|
||||
#endif
|
||||
|
@ -759,6 +483,15 @@ static void Gfx_RestoreState(void) {
|
|||
}
|
||||
cc_bool Gfx_WarnIfNecessary(void) { return false; }
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------------Drawing--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
typedef void (*GL_SetupVBFunc)(void);
|
||||
typedef void (*GL_SetupVBRangeFunc)(int startVertex);
|
||||
static GL_SetupVBFunc gfx_setupVBFunc;
|
||||
static GL_SetupVBRangeFunc gfx_setupVBRangeFunc;
|
||||
|
||||
static void GL_SetupVbColoured(void) {
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, false, SIZEOF_VERTEX_COLOURED, (void*)0);
|
||||
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, SIZEOF_VERTEX_COLOURED, (void*)12);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#if defined CC_BUILD_WEB || defined CC_BUILD_ANDROID
|
||||
#define PIXEL_FORMAT GL_RGBA
|
||||
#else
|
||||
#define PIXEL_FORMAT 0x80E1 /* GL_BGRA_EXT */
|
||||
#define PIXEL_FORMAT GL_BGRA_EXT
|
||||
#endif
|
||||
#define _GL_TEXTURE_MAX_LEVEL 0x813D
|
||||
|
||||
#if defined CC_BIG_ENDIAN
|
||||
/* Pixels are stored in memory as A,R,G,B but GL_UNSIGNED_BYTE will interpret as B,G,R,A */
|
||||
|
@ -22,14 +23,14 @@ static void GL_UpdateVsync(void) {
|
|||
GLContext_SetFpsLimit(gfx_vsync, gfx_minFrameMs);
|
||||
}
|
||||
|
||||
static void GL_CheckSupport(void);
|
||||
static void GLBackend_Init(void);
|
||||
void Gfx_Create(void) {
|
||||
GLContext_Create();
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &Gfx.MaxTexWidth);
|
||||
Gfx.MaxTexHeight = Gfx.MaxTexWidth;
|
||||
Gfx.Created = true;
|
||||
|
||||
GL_CheckSupport();
|
||||
GLBackend_Init();
|
||||
Gfx_RestoreState();
|
||||
GL_UpdateVsync();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue