#include "GLRenderDevice.h" #include "SdlBFApp.h" #include "BFWindow.h" #include "img/ImageData.h" #include "util/PerfTimer.h" #include "SDL_video.h" USING_NS_BF; #define NOT_IMPL throw "Not implemented" #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 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) value <<= 1; 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]) { memset(matrix, 0, sizeof(float) * 4 * 4); float invRL = 1.0f / (right - left); float invTB = 1.0f / (top - bottom); float invFN = 1.0f / (zFar - zNear); 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 = NULL; } GLShaderParam::~GLShaderParam() { } 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; //float v[4] = {x, y, z, w}; //GLCHECK(mGLVariable->AsVector()->SetFloatVector(v)); } /// GLShader::GLShader() { } GLShader::~GLShader() { GLShaderParamMap::iterator itr = mParamsMap.begin(); while (itr != mParamsMap.end()) { delete itr->second; ++itr; } //if (mGLEffect != NULL) //mGLEffect->Release(); } ShaderParam* GLShader::GetShaderParam(const std::wstring& name) { /*GLShaderParamMap::iterator itr = mParamsMap.find(name); if (itr != mParamsMap.end()) return itr->second; IGL10EffectVariable* d3DVariable = mGLEffect->GetVariableByName(ToString(name).c_str()); if (d3DVariable == NULL) return NULL; GLShaderParam* shaderParam = new GLShaderParam(); shaderParam->mGLVariable = d3DVariable; mParamsMap[name] = shaderParam; return shaderParam;*/ NOT_IMPL; return NULL; } /// GLTexture::GLTexture() { mGLTexture = NULL; //mGLRenderTargetView = NULL; mRenderDevice = NULL; } GLTexture::~GLTexture() { //if (mGLTexture != NULL) //mGLTexture->Release(); } void GLTexture::PhysSetAsTarget() { NOT_IMPL; //{ // GL10_VIEWPORT viewPort; // viewPort.Width = mWidth; // viewPort.Height = mHeight; // viewPort.MinDepth = 0.0f; // viewPort.MaxDepth = 1.0f; // viewPort.TopLeftX = 0; // viewPort.TopLeftY = 0; // mRenderDevice->mGLDevice->RSSetViewports(1, &viewPort); // mRenderDevice->mGLDevice->OMSetRenderTargets(1, &mGLRenderTargetView, NULL); //} //if (!mHasBeenDrawnTo) //{ // //mRenderDevice->mGLDevice->ClearRenderTargetView(mGLRenderTargetView, D3GLVECTOR4(1, 0.5, 0.5, 1)); // mHasBeenDrawnTo = true; //} } /// GLDrawBatch::GLDrawBatch(int minVtxSize, int minIdxSize) : DrawBatch() { mAllocatedVertices = 16*1024; // Alloc more indices than vertices. Worst case is really long tri strip. mAllocatedIndices = mAllocatedVertices * 3; if (minVtxSize > mAllocatedVertices) mAllocatedVertices = GetPowerOfTwo(minVtxSize); if (minIdxSize > mAllocatedIndices) mAllocatedIndices = GetPowerOfTwo(minIdxSize); mVertices = new Vertex3D[mAllocatedVertices]; mIndices = new uint16[mAllocatedIndices]; mNext = NULL; } GLDrawBatch::~GLDrawBatch() { delete mVertices; delete mIndices; //mGLBuffer->Release(); } void GLDrawBatch::Lock() { //mGLBuffer->Map(GL10_MAP_WRITE_DISCARD, 0, (void**) &mVertices); } extern int gBFDrawBatchCount; void GLDrawBatch::Draw() { if (mIdxIdx == 0) return; gBFDrawBatchCount++; GLRenderDevice* glRenderDevice = (GLRenderDevice*) gBFApp->mRenderDevice; if (glRenderDevice->mPhysRenderWindow != mDrawLayer->mRenderWindow) glRenderDevice->PhysSetRenderWindow(mDrawLayer->mRenderWindow); //// Flip BGRA to RGBA //for (int i = 0; i < mIdx; i++) //{ // uint32 aColor = mVertices[i].color; // aColor = // (aColor & 0xFF00FF00) | // ((aColor & 0x00FF0000) >> 16) | // ((aColor & 0x000000FF) << 16); // mVertices[i].color = aColor; //} //mGLBuffer->Unmap(); //GLShader* curShader = (GLShader*) aRenderDevice->mCurShader; GLShader* curShader = (GLShader*) mCurShader; //if (curShader->mTextureParam != NULL) //curShader->mTextureParam->SetTexture(mCurTexture); #ifdef BF_PLATFORM_OPENGL_ES2 //bf_glClientActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, ((GLTexture*)mCurTexture)->mGLTexture); glUniform1i(curShader->mAttribTex0, 0); //bf_glClientActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, ((GLTexture*)mCurTexture)->mGLTexture2); glUniform1i(curShader->mAttribTex1, 1); //glEnable(GL_TEXTURE_2D); #else glBindTexture(GL_TEXTURE_2D, ((GLTexture*)mCurTexture)->mGLTexture); #endif //if (mIsAdditive != glRenderDevice->mCurAdditive) //glRenderDevice->PhysSetAdditive(mIsAdditive); //TODO: Just do 'apply', we don't have to do full PhysSetShaderPass if (curShader != glRenderDevice->mPhysShader) glRenderDevice->PhysSetShader(mCurShader); // Set vertex buffer if (glRenderDevice->mGLVertexBuffer == 0) { bf_glGenBuffers(1, &glRenderDevice->mGLVertexBuffer); bf_glGenBuffers(1, &glRenderDevice->mGLIndexBuffer); } bf_glBindBuffer(GL_ARRAY_BUFFER, glRenderDevice->mGLVertexBuffer); bf_glBufferData(GL_ARRAY_BUFFER, mVtxIdx * sizeof(Vertex3D), mVertices, GL_STREAM_DRAW); bf_glVertexAttribPointer(curShader->mAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void*)offsetof(Vertex3D, x)); bf_glVertexAttribPointer(curShader->mAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void*)offsetof(Vertex3D, u)); bf_glVertexAttribPointer(curShader->mAttribColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex3D), (void*)offsetof(Vertex3D, color)); 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); 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(); } DrawBatch* GLDrawLayer::AllocateBatch(int minVtxCount, int minIdxCount) { AutoPerf autoPerf("GLDrawLayer::AllocateBatch"); //GLDrawBatchVector* pool = &((GLRenderDevice*) gBFApp->mRenderDevice)->mDrawBatchPool; GLRenderDevice* glRenderDevice = (GLRenderDevice*)gBFApp->mRenderDevice; GLDrawBatch* newBatch = NULL; //TODO: Search GLDrawBatch** prevRefPtr = &glRenderDevice->mFreeBatchHead; GLDrawBatch* checkBatch = glRenderDevice->mFreeBatchHead; while (checkBatch != NULL) { if ((checkBatch->mAllocatedVertices >= minVtxCount) && (checkBatch->mAllocatedIndices >= minIdxCount)) { newBatch = checkBatch; *prevRefPtr = (GLDrawBatch*)checkBatch->mNext; checkBatch->mNext = NULL; break; } checkBatch = (GLDrawBatch*)checkBatch->mNext; prevRefPtr = (GLDrawBatch**)&checkBatch->mNext; } /*for (int i = pool->size() -1; i >= 0; i--) { GLDrawBatch* checkBatch = (*pool)[i]; if ((checkBatch->mAllocatedVertices >= minVtxCount) && (checkBatch->mAllocatedIndices >= minIdxCount)) { newBatch = checkBatch; pool->erase(pool->begin() + i); break; } }*/ if (newBatch == NULL) newBatch = new GLDrawBatch(minVtxCount, minIdxCount); newBatch->mDrawLayer = this; return newBatch; } void GLDrawLayer::FreeBatch(DrawBatch* drawBatch) { //delete drawBatch; GLDrawBatch* batch = (GLDrawBatch*) drawBatch; batch->Clear(); //GLDrawBatchVector* pool = &((GLRenderDevice*) gBFApp->mRenderDevice)->mDrawBatchPool; //pool->push_back(batch); GLRenderDevice* glRenderDevice = (GLRenderDevice*)gBFApp->mRenderDevice; drawBatch->mNext = glRenderDevice->mFreeBatchHead; glRenderDevice->mFreeBatchHead = batch; } void GLRenderDevice::PhysSetShader(Shader* shader) { GLRenderDevice* aRenderDevice = (GLRenderDevice*) gBFApp->mRenderDevice; //TODO: Cache more GLShader* glShader = (GLShader*)shader; GLfloat matrix[4][4]; CreateOrthographicOffCenter(0.0f, (float)mPhysRenderWindow->mWidth, (float)mPhysRenderWindow->mHeight, 0.0f, -100.0f, 100.0f, matrix); GLint matrixLoc = bf_glGetUniformLocation(glShader->mGLProgram, "screenMatrix"); //BF_ASSERT(matrixLoc >= 0); if (matrixLoc >= 0) bf_glUniformMatrix4fv(matrixLoc, 1, false, (float*)matrix); /*mPhysShaderPass = shaderPass; GLShaderPass* dXShaderPass = (GLShaderPass*) mPhysShaderPass; mGLDevice->IASetInputLayout(dXShaderPass->mGLLayout); if (mCurShader->mLastResizeCount != mCurRenderTarget->mResizeNum) { ShaderParam* shaderParam = mCurShader->GetShaderParam(L"WindowSize"); if (shaderParam != NULL) { shaderParam->SetFloat2((float) mCurRenderTarget->mWidth, (float) mCurRenderTarget->mHeight); } mCurShader->mLastResizeCount = mCurRenderTarget->mResizeNum; } GLCHECK(dXShaderPass->mGLEffectPass->Apply(0));*/ /*GLfloat matrix[4][4]; CreateOrthographicOffCenter(0.0f, (float)mPhysRenderWindow->mWidth, (float)mPhysRenderWindow->mHeight, 0.0f, -100.0f, 100.0f, matrix); GLint uniformLocation = bf_glGetUniformLocation(((GLShader*)shaderPass->mTechnique->mShader)->mGLProgram, "screenMatrix"); if (uniformLocation != -1) bf_glUniformMatrix4fv(uniformLocation, 1, false, (GLfloat*)matrix);*/ } void GLRenderDevice::PhysSetRenderWindow(RenderWindow* renderWindow) { mCurRenderTarget = renderWindow; mPhysRenderWindow = renderWindow; ((GLRenderWindow*)renderWindow)->PhysSetAsTarget(); } void GLRenderDevice::PhysSetRenderTarget(Texture* renderTarget) { mCurRenderTarget = renderTarget; renderTarget->PhysSetAsTarget(); } /// template static void BFGetGLProc(T& proc, const char* name) { proc = (T)SDL_GL_GetProcAddress(name); } #define BF_GET_GLPROC(name) BFGetGLProc(bf_##name, #name) GLRenderWindow::GLRenderWindow(GLRenderDevice* renderDevice, SDL_Window* sdlWindow) { if (bf_glGenBuffers == NULL) { 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); BF_GET_GLPROC(glUniform4f); BF_GET_GLPROC(glUniformMatrix4fv); BF_GET_GLPROC(glGetObjectParameterivARB); BF_GET_GLPROC(glCompressedTexImage2D); BF_GET_GLPROC(glClientActiveTexture); #if !defined BF_PLATFORM_OPENGL_ES2 BF_GET_GLPROC(glGetVertexAttribdv); #endif } mSDLWindow = sdlWindow; mRenderDevice = renderDevice; Resized(); //mGLSwapChain = NULL; //mGLBackBuffer = NULL; //mGLRenderTargetView = NULL; //mRenderDevice = renderDevice; //mHWnd = hWnd; //HRESULT hr = S_OK; //Resized(); //GLGI_SWAP_CHAIN_DESC swapChainDesc; //ZeroMemory( &swapChainDesc, sizeof(swapChainDesc) ); //swapChainDesc.BufferCount = 1; //swapChainDesc.BufferDesc.Width = mWidth; //swapChainDesc.BufferDesc.Height = mHeight; //swapChainDesc.BufferDesc.Format = GLGI_FORMAT_R8G8B8A8_UNORM; //swapChainDesc.BufferUsage = GLGI_USAGE_RENDER_TARGET_OUTPUT; //swapChainDesc.OutputWindow = mHWnd; //swapChainDesc.SampleDesc.Count = 1; //swapChainDesc.SampleDesc.Quality = 0; //swapChainDesc.Windowed = TRUE; ////swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; ////swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; ////swapChainDesc.Flags = GLGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // IGLGIDevice* pGLGIDevice = NULL; // mRenderDevice->mGLDevice->QueryInterface(__uuidof(IGLGIDevice), (void**) &pGLGIDevice ); // GLCHECK(mRenderDevice->mGLGIFactory->CreateSwapChain(pGLGIDevice, &swapChainDesc, &mGLSwapChain)); // pGLGIDevice->Release(); // pGLGIDevice = NULL; // //GLCHECK(mGLSwapChain->GetBuffer(0, __uuidof(IGL10Texture2D), (LPVOID*)&mGLBackBuffer)); //GLCHECK(mRenderDevice->mGLDevice->CreateRenderTargetView(mGLBackBuffer, NULL, &mGLRenderTargetView)); } GLRenderWindow::~GLRenderWindow() { /*if (mGLRenderTargetView != NULL) mGLRenderTargetView->Release(); if (mGLBackBuffer != NULL) mGLBackBuffer->Release(); if (mGLSwapChain != NULL) mGLSwapChain->Release(); */ } 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); //TODO: Set matrix variable //glMatrixMode(GL_MODELVIEW); //glLoadMatrixf((const GLfloat*)matrix); //NOT_IMPL; ////if (mRenderDevice->mCurRenderTarget != this) //{ // GL10_VIEWPORT viewPort; // viewPort.Width = mWidth; // viewPort.Height = mHeight; // viewPort.MinDepth = 0.0f; // viewPort.MaxDepth = 1.0f; // viewPort.TopLeftX = 0; // viewPort.TopLeftY = 0; // // mRenderDevice->mGLDevice->OMSetRenderTargets(1, &mGLRenderTargetView, NULL); // mRenderDevice->mGLDevice->RSSetViewports(1, &viewPort); //} //if (!mHasBeenDrawnTo) //{ // //mRenderDevice->mGLDevice->ClearRenderTargetView(mGLRenderTargetView, D3GLVECTOR4(rand() / (float) RAND_MAX, 0, 1, 0)); // mRenderDevice->mGLDevice->ClearRenderTargetView(mGLRenderTargetView, D3GLVECTOR4(0, 0, 0, 0)); //} //mHasBeenDrawnTo = true; } void GLRenderWindow::SetAsTarget() { //TODO: Handle this more elegantly when we actually handle draw layers properly... //if (mRenderDevice->mCurRenderTarget != NULL) //mRenderDevice->mCurDrawLayer->Flush(); mHasBeenTargeted = true; mRenderDevice->mCurRenderTarget = this; } 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)); GLCHECK(mGLSwapChain->GetBuffer(0, __uuidof(IGL10Texture2D), (LPVOID*)&mGLBackBuffer)); GLCHECK(mRenderDevice->mGLDevice->CreateRenderTargetView(mGLBackBuffer, NULL, &mGLRenderTargetView)); }*/ } void GLRenderWindow::Present() { SDL_GL_SwapWindow(mSDLWindow); //GLCHECK(mGLSwapChain->Present((mWindow->mFlags & BFWINDOW_VSYNC) ? 1 : 0, 0)); } void GLRenderWindow::CopyBitsTo(uint32* dest, int width, int height) { 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() { //mGLDevice = NULL; mGLVertexBuffer = 0; mGLIndexBuffer = 0; mBlankTexture = 0; mFreeBatchHead = NULL; } GLRenderDevice::~GLRenderDevice() { } bool GLRenderDevice::Init(BFApp* app) { SdlBFApp* winApp = (SdlBFApp*) app; /// ////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(&pGLGIDevice))); //IGLGIAdapter* pGLGIAdapter = NULL; //GLCHECK(pGLGIDevice->GetParent(__uuidof(IGLGIAdapter), reinterpret_cast(&pGLGIAdapter))); //IGLGIFactory* pGLGIFactory = NULL; //GLCHECK(pGLGIAdapter->GetParent(__uuidof(IGLGIFactory), reinterpret_cast(&mGLGIFactory))); ////set rasterizer //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; // //mGLDevice->CreateRasterizerState( &rasterizerState, &mGLRasterizerStateClipped); // //rasterizerState.ScissorEnable = false; //mGLDevice->CreateRasterizerState( &rasterizerState, &mGLRasterizerStateUnclipped); //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() { mCurRenderTarget = NULL; mPhysRenderWindow = NULL; mPhysShader = NULL; RenderWindowList::iterator itr = mRenderWindowList.begin(); while (itr != mRenderWindowList.end()) { (*itr)->mHasBeenDrawnTo = false; (*itr)->mHasBeenTargeted = false; ++itr; } } void GLRenderDevice::FrameEnd() { RenderWindowList::iterator itr = mRenderWindowList.begin(); while (itr != mRenderWindowList.end()) { RenderWindow* aRenderWindow = *itr; if (aRenderWindow->mHasBeenTargeted) { //aRenderWindow->mCurDrawLayer->Flush(); DrawLayerList::iterator drawLayerItr = aRenderWindow->mDrawLayerList.begin(); while (drawLayerItr != aRenderWindow->mDrawLayerList.end()) { DrawLayer* drawLayer = *drawLayerItr; drawLayer->Flush(); ++drawLayerItr; } aRenderWindow->Present(); } ++itr; } } Texture* GLRenderDevice::LoadTexture(ImageData* imageData, bool additive) { imageData->mIsAdditive = additive; imageData->PremultiplyAlpha(); //int w = power_of_two(imageData->mWidth); //int h = power_of_two(imageData->mHeight); if (mBlankTexture == 0) { glGenTextures(1, &mBlankTexture); glBindTexture(GL_TEXTURE_2D, 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); } GLTexture* glTexture = new GLTexture(); glTexture->mGLTexture2 = mBlankTexture; int texCount = 0; 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, imageData->mWidth, imageData->mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData->mBits); } glPixelStorei(GL_UNPACK_ALIGNMENT, 1); if (texNum == 0) glTexture->mGLTexture = glTextureID; else glTexture->mGLTexture2 = glTextureID; } glTexture->mWidth = imageData->mWidth; glTexture->mHeight = imageData->mHeight; glTexture->AddRef(); return glTexture; //IGL10ShaderResourceView* d3DShaderResourceView = NULL; //imageData->PremultiplyAlpha(); //int aWidth = 0; //int aHeight = 0; // //// Create the render target texture //GL10_TEXTURE2D_DESC desc; //ZeroMemory(&desc, sizeof(desc)); //desc.Width = imageData->mWidth; //desc.Height = imageData->mHeight; //desc.MipLevels = 1; //desc.ArraySize = 1; //desc.Format = GLGI_FORMAT_R8G8B8A8_UNORM; //desc.SampleDesc.Count = 1; //desc.Usage = GL10_USAGE_DYNAMIC; //desc.CPUAccessFlags = GL10_CPU_ACCESS_WRITE; //desc.BindFlags = GL10_BIND_SHADER_RESOURCE; //IGL10Texture2D* d3DTexture = NULL; //GLCHECK(mGLDevice->CreateTexture2D(&desc, NULL, &d3DTexture)); //aWidth = imageData->mWidth; //aHeight = imageData->mHeight; //GL10_MAPPED_TEXTURE2D mapTex; //GLCHECK(d3DTexture->Map(GL10CalcSubresource(0, 0, 1), GL10_MAP_WRITE_DISCARD, 0, &mapTex)); //uint8* destPtr = (uint8*) mapTex.pData; //uint8* srcPtr = (uint8*) imageData->mBits; //for (int y = 0; y < imageData->mHeight; y++) //{ // memcpy(destPtr, srcPtr, aWidth*sizeof(uint32)); // srcPtr += aWidth*sizeof(uint32); // destPtr += mapTex.RowPitch; //} //d3DTexture->Unmap(0); //GL10_SHADER_RESOURCE_VIEW_DESC srDesc; //srDesc.Format = desc.Format; //srDesc.ViewDimension = GL10_SRV_DIMENSION_TEXTURE2D; //srDesc.Texture2D.MostDetailedMip = 0; //srDesc.Texture2D.MipLevels = 1; // //GLCHECK(mGLDevice->CreateShaderResourceView(d3DTexture, &srDesc, &d3DShaderResourceView)); //GLTexture* aTexture = new GLTexture(); //aTexture->mWidth = aWidth; //aTexture->mHeight = aHeight; //aTexture->mGLTexture = d3DShaderResourceView; //aTexture->AddRef(); //return aTexture; } Shader* GLRenderDevice::LoadShader(const StringImpl& fileName) { GLShader* glShader = new GLShader(); glShader->mGLVertexShader = bf_glCreateShader(GL_VERTEX_SHADER); glShader->mGLFragmentShader = bf_glCreateShader(GL_FRAGMENT_SHADER); GLint vertProgramLen = 0; GLint fragProgramLen = 0; #ifdef BF_PLATFORM_OPENGL_ES2 GLchar* vertProgram = (GLchar*)LoadBinaryData(fileName + L"_es.vert", &vertProgramLen); GLchar* fragProgram = (GLchar*)LoadBinaryData(fileName + L"_es.frag", &fragProgramLen); #else GLchar* vertProgram = (GLchar*)LoadBinaryData(fileName + L".vert", &vertProgramLen); GLchar* fragProgram = (GLchar*)LoadBinaryData(fileName + L".frag", &fragProgramLen); #endif if ((vertProgram == NULL) || (fragProgram == NULL)) { delete vertProgram; delete fragProgram; return NULL; } int infoLogLen = 0; char infoLog[2048]; bf_glShaderSource(glShader->mGLVertexShader, 1, (const GLchar**)&vertProgram, &vertProgramLen); bf_glCompileShader(glShader->mGLVertexShader); bf_glGetShaderInfoLog(glShader->mGLVertexShader, 2048, &infoLogLen, infoLog); GLint compiled = 0; //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()); 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); bf_glUseProgram(glShader->mGLProgram); 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"); if (glShader->mAttribPosition >= 0) bf_glEnableVertexAttribArray(glShader->mAttribPosition); if (glShader->mAttribTexCoord0 >= 0) bf_glEnableVertexAttribArray(glShader->mAttribTexCoord0); if (glShader->mAttribColor >= 0) bf_glEnableVertexAttribArray(glShader->mAttribColor); return glShader; } void GLRenderDevice::SetShader(Shader* shader) { mShaderChanged = true; mCurShader = shader; } void GLRenderDevice::PhysSetAdditive(bool additive) { if (additive) glBlendFunc(GL_SRC_ALPHA, GL_ONE); else glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); mCurAdditive = additive; } void GLRenderDevice::SetClip(float x, float y, float width, float height) { //TODO: Store state in draw batcher mCurDrawLayer->Flush(); NOT_IMPL; /*GL10_RECT rects[1]; rects[0].left = (int) x; rects[0].right = (int) (x + width); rects[0].top = (int) y; rects[0].bottom = (int) (y + height); mGLDevice->RSSetScissorRects(1, rects); mGLDevice->RSSetState(mGLRasterizerStateClipped);*/ } void GLRenderDevice::DisableClip() { mCurDrawLayer->Flush(); NOT_IMPL; //mGLDevice->RSSetState(mGLRasterizerStateUnclipped); } Texture* GLRenderDevice::CreateRenderTarget(int width, int height, bool destAlpha) { NOT_IMPL; //IGL10ShaderResourceView* d3DShaderResourceView = NULL; // //int aWidth = 0; //int aHeight = 0; // //// Create the render target texture //GL10_TEXTURE2D_DESC desc; //ZeroMemory(&desc, sizeof(desc)); //desc.Width = width; //desc.Height = height; //desc.MipLevels = 1; //desc.ArraySize = 1; //desc.Format = GLGI_FORMAT_R8G8B8A8_UNORM; //desc.SampleDesc.Count = 1; //UINT qualityLevels = 0; //int samples = 1; //GLCHECK(mGLDevice->CheckMultisampleQualityLevels(GLGI_FORMAT_R8G8B8A8_UNORM, samples, &qualityLevels)); //desc.SampleDesc.Count = samples; //desc.SampleDesc.Quality = qualityLevels-1; //desc.Usage = GL10_USAGE_DEFAULT; //desc.CPUAccessFlags = 0; //GL10_CPU_ACCESS_WRITE; //desc.BindFlags = GL10_BIND_SHADER_RESOURCE | GL10_BIND_RENDER_TARGET; //IGL10Texture2D* d3DTexture = NULL; //GLCHECK(mGLDevice->CreateTexture2D(&desc, NULL, &d3DTexture)); //aWidth = width; //aHeight = height; //GL10_SHADER_RESOURCE_VIEW_DESC srDesc; //srDesc.Format = desc.Format; //srDesc.ViewDimension = GL10_SRV_DIMENSION_TEXTURE2D; //srDesc.Texture2D.MostDetailedMip = 0; //srDesc.Texture2D.MipLevels = 1; // //if (qualityLevels != 0) //{ // srDesc.ViewDimension = GL10_SRV_DIMENSION_TEXTURE2DMS; //} //GLCHECK(mGLDevice->CreateShaderResourceView(d3DTexture, &srDesc, &d3DShaderResourceView)); // //IGL10RenderTargetView* d3DRenderTargetView; //GLCHECK(mGLDevice->CreateRenderTargetView(d3DTexture, NULL, &d3DRenderTargetView)); //GLTexture* aRenderTarget = new GLTexture(); //aRenderTarget->mWidth = width; //aRenderTarget->mHeight = height; //aRenderTarget->mRenderDevice = this; //aRenderTarget->mGLTexture = d3DShaderResourceView; //aRenderTarget->mGLRenderTargetView = d3DRenderTargetView; //aRenderTarget->AddRef(); //return aRenderTarget; }