diff options
| author | Jasper St. Pierre <jstpierre@mecheye.net> | 2013-09-10 23:12:54 -0400 |
|---|---|---|
| committer | Jasper St. Pierre <jstpierre@mecheye.net> | 2013-10-07 10:37:01 -0400 |
| commit | a7c72081039ca1c6bee6b18db44fe4e9ffaf4fb5 (patch) | |
| tree | 70e3c53d290bf5f0e76a2f3295b4ff01e07e2127 /Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp | |
| parent | d6f0ecebb4742f6b41397420f7d58ab7a05a03cc (diff) | |
Put Plugins/ in Core/, rename to VideoBackends
Diffstat (limited to 'Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp b/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp new file mode 100644 index 0000000000..5e3e4a4ae0 --- /dev/null +++ b/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp @@ -0,0 +1,369 @@ +// Copyright 2013 Dolphin Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "Common.h" +#include "MemoryUtil.h" + +#include <VideoCommon.h> + +#include "BPMemLoader.h" +#include "HwRasterizer.h" +#include "NativeVertexFormat.h" +#include "DebugUtil.h" + +#define TEMP_SIZE (1024*1024*4) + +namespace HwRasterizer +{ + float efbHalfWidth; + float efbHalfHeight; + bool hasTexture; + + u8 *temp; + + // Programs + static GLuint colProg, texProg, clearProg; + + // Color + static GLint col_apos = -1, col_atex = -1; + // Tex + static GLint tex_apos = -1, tex_atex = -1, tex_utex = -1; + // Clear shader + static GLint clear_apos = -1, clear_ucol = -1; + + void CreateShaders() + { + // Color Vertices + static const char *fragcolText = + "varying " PREC " vec4 TexCoordOut;\n" + "void main() {\n" + " gl_FragColor = TexCoordOut;\n" + "}\n"; + // Texture Vertices + static const char *fragtexText = + "varying " PREC " vec4 TexCoordOut;\n" + "uniform " TEXTYPE " Texture;\n" + "void main() {\n" + " gl_FragColor = " TEXFUNC "(Texture, TexCoordOut.xy);\n" + "}\n"; + // Clear shader + static const char *fragclearText = + "uniform " PREC " vec4 Color;\n" + "void main() {\n" + " gl_FragColor = Color;\n" + "}\n"; + // Generic passthrough vertice shaders + static const char *vertShaderText = + "attribute vec4 pos;\n" + "attribute vec4 TexCoordIn;\n " + "varying vec4 TexCoordOut;\n " + "void main() {\n" + " gl_Position = pos;\n" + " TexCoordOut = TexCoordIn;\n" + "}\n"; + static const char *vertclearText = + "attribute vec4 pos;\n" + "void main() {\n" + " gl_Position = pos;\n" + "}\n"; + + // Color Program + colProg = OpenGL_CompileProgram(vertShaderText, fragcolText); + + // Texture Program + texProg = OpenGL_CompileProgram(vertShaderText, fragtexText); + + // Clear Program + clearProg = OpenGL_CompileProgram(vertclearText, fragclearText); + + // Color attributes + col_apos = glGetAttribLocation(colProg, "pos"); + col_atex = glGetAttribLocation(colProg, "TexCoordIn"); + // Texture attributes + tex_apos = glGetAttribLocation(texProg, "pos"); + tex_atex = glGetAttribLocation(texProg, "TexCoordIn"); + tex_utex = glGetUniformLocation(texProg, "Texture"); + // Clear attributes + clear_apos = glGetAttribLocation(clearProg, "pos"); + clear_ucol = glGetUniformLocation(clearProg, "Color"); + } + + void Init() + { + efbHalfWidth = EFB_WIDTH / 2.0f; + efbHalfHeight = 480 / 2.0f; + + temp = (u8*)AllocateMemoryPages(TEMP_SIZE); + } + void Shutdown() + { + glDeleteProgram(colProg); + glDeleteProgram(texProg); + glDeleteProgram(clearProg); + } + void Prepare() + { + //legacy multitexturing: select texture channel only. + glActiveTexture(GL_TEXTURE0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment +#ifndef USE_GLES + glShadeModel(GL_SMOOTH); + glDisable(GL_BLEND); + glClearDepth(1.0f); + glEnable(GL_SCISSOR_TEST); + glDisable(GL_LIGHTING); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glClientActiveTexture(GL_TEXTURE0); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_TEXTURE_RECTANGLE_ARB); + glStencilFunc(GL_ALWAYS, 0, 0); + glDisable(GL_STENCIL_TEST); +#endif + // used by hw rasterizer if it enables blending and depth test + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthFunc(GL_LEQUAL); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + CreateShaders(); + GL_REPORT_ERRORD(); + } + static float width, height; + void LoadTexture() + { + FourTexUnits &texUnit = bpmem.tex[0]; + u32 imageAddr = texUnit.texImage3[0].image_base; + // Texture Rectangle uses pixel coordinates + // While GLES uses texture coordinates +#ifdef USE_GLES + width = texUnit.texImage0[0].width; + height = texUnit.texImage0[0].height; +#else + width = 1; + height = 1; +#endif + TexCacheEntry &cacheEntry = textures[imageAddr]; + cacheEntry.Update(); + + glBindTexture(TEX2D, cacheEntry.texture); + glTexParameteri(TEX2D, GL_TEXTURE_MAG_FILTER, texUnit.texMode0[0].mag_filter ? GL_LINEAR : GL_NEAREST); + glTexParameteri(TEX2D, GL_TEXTURE_MIN_FILTER, (texUnit.texMode0[0].min_filter >= 4) ? GL_LINEAR : GL_NEAREST); + GL_REPORT_ERRORD(); + } + + void BeginTriangles() + { + // disabling depth test sometimes allows more things to be visible + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + + hasTexture = bpmem.tevorders[0].enable0; + + if (hasTexture) + LoadTexture(); + } + + void EndTriangles() + { + glBindTexture(TEX2D, 0); + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + } + + void DrawColorVertex(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2) + { + float x0 = (v0->screenPosition.x / efbHalfWidth) - 1.0f; + float y0 = 1.0f - (v0->screenPosition.y / efbHalfHeight); + float z0 = v0->screenPosition.z / (float)0x00ffffff; + + float x1 = (v1->screenPosition.x / efbHalfWidth) - 1.0f; + float y1 = 1.0f - (v1->screenPosition.y / efbHalfHeight); + float z1 = v1->screenPosition.z / (float)0x00ffffff; + + float x2 = (v2->screenPosition.x / efbHalfWidth) - 1.0f; + float y2 = 1.0f - (v2->screenPosition.y / efbHalfHeight); + float z2 = v2->screenPosition.z / (float)0x00ffffff; + + float r0 = v0->color[0][OutputVertexData::RED_C] / 255.0f; + float g0 = v0->color[0][OutputVertexData::GRN_C] / 255.0f; + float b0 = v0->color[0][OutputVertexData::BLU_C] / 255.0f; + + float r1 = v1->color[0][OutputVertexData::RED_C] / 255.0f; + float g1 = v1->color[0][OutputVertexData::GRN_C] / 255.0f; + float b1 = v1->color[0][OutputVertexData::BLU_C] / 255.0f; + + float r2 = v2->color[0][OutputVertexData::RED_C] / 255.0f; + float g2 = v2->color[0][OutputVertexData::GRN_C] / 255.0f; + float b2 = v2->color[0][OutputVertexData::BLU_C] / 255.0f; + + static const GLfloat verts[3][3] = { + { x0, y0, z0 }, + { x1, y1, z1 }, + { x2, y2, z2 } + }; + static const GLfloat col[3][4] = { + { r0, g0, b0, 1.0f }, + { r1, g1, b1, 1.0f }, + { r2, g2, b2, 1.0f } + }; + { + glUseProgram(colProg); + glEnableVertexAttribArray(col_apos); + glEnableVertexAttribArray(col_atex); + + glVertexAttribPointer(col_apos, 3, GL_FLOAT, GL_FALSE, 0, verts); + glVertexAttribPointer(col_atex, 4, GL_FLOAT, GL_FALSE, 0, col); + glDrawArrays(GL_TRIANGLES, 0, 3); + glDisableVertexAttribArray(col_atex); + glDisableVertexAttribArray(col_apos); + } + GL_REPORT_ERRORD(); + } + + void DrawTextureVertex(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2) + { + float x0 = (v0->screenPosition.x / efbHalfWidth) - 1.0f; + float y0 = 1.0f - (v0->screenPosition.y / efbHalfHeight); + float z0 = v0->screenPosition.z; + + float x1 = (v1->screenPosition.x / efbHalfWidth) - 1.0f; + float y1 = 1.0f - (v1->screenPosition.y / efbHalfHeight); + float z1 = v1->screenPosition.z; + + float x2 = (v2->screenPosition.x / efbHalfWidth) - 1.0f; + float y2 = 1.0f - (v2->screenPosition.y / efbHalfHeight); + float z2 = v2->screenPosition.z; + + float s0 = v0->texCoords[0].x / width; + float t0 = v0->texCoords[0].y / height; + + float s1 = v1->texCoords[0].x / width; + float t1 = v1->texCoords[0].y / height; + + float s2 = v2->texCoords[0].x / width; + float t2 = v2->texCoords[0].y / height; + + static const GLfloat verts[3][3] = { + { x0, y0, z0 }, + { x1, y1, z1 }, + { x2, y2, z2 } + }; + static const GLfloat tex[3][2] = { + { s0, t0 }, + { s1, t1 }, + { s2, t2 } + }; + { + glUseProgram(texProg); + glEnableVertexAttribArray(tex_apos); + glEnableVertexAttribArray(tex_atex); + + glVertexAttribPointer(tex_apos, 3, GL_FLOAT, GL_FALSE, 0, verts); + glVertexAttribPointer(tex_atex, 2, GL_FLOAT, GL_FALSE, 0, tex); + glUniform1i(tex_utex, 0); + glDrawArrays(GL_TRIANGLES, 0, 3); + glDisableVertexAttribArray(tex_atex); + glDisableVertexAttribArray(tex_apos); + } + GL_REPORT_ERRORD(); + } + + void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2) + { + if (hasTexture) + DrawTextureVertex(v0, v1, v2); + else + DrawColorVertex(v0, v1, v2); + } + + void Clear() + { + u8 r = (bpmem.clearcolorAR & 0x00ff); + u8 g = (bpmem.clearcolorGB & 0xff00) >> 8; + u8 b = (bpmem.clearcolorGB & 0x00ff); + u8 a = (bpmem.clearcolorAR & 0xff00) >> 8; + + GLfloat left = (GLfloat)bpmem.copyTexSrcXY.x / efbHalfWidth - 1.0f; + GLfloat top = 1.0f - (GLfloat)bpmem.copyTexSrcXY.y / efbHalfHeight; + GLfloat right = (GLfloat)(left + bpmem.copyTexSrcWH.x + 1) / efbHalfWidth - 1.0f; + GLfloat bottom = 1.0f - (GLfloat)(top + bpmem.copyTexSrcWH.y + 1) / efbHalfHeight; + GLfloat depth = (GLfloat)bpmem.clearZValue / (GLfloat)0x00ffffff; + static const GLfloat verts[4][3] = { + { left, top, depth }, + { right, top, depth }, + { right, bottom, depth }, + { left, bottom, depth } + }; + { + glUseProgram(clearProg); + glVertexAttribPointer(clear_apos, 3, GL_FLOAT, GL_FALSE, 0, verts); + glUniform4f(clear_ucol, r, g, b, a); + glEnableVertexAttribArray(col_apos); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableVertexAttribArray(col_apos); + } + GL_REPORT_ERRORD(); + } + + TexCacheEntry::TexCacheEntry() + { + Create(); + } + + void TexCacheEntry::Create() + { + FourTexUnits &texUnit = bpmem.tex[0]; + + texImage0.hex = texUnit.texImage0[0].hex; + texImage1.hex = texUnit.texImage1[0].hex; + texImage2.hex = texUnit.texImage2[0].hex; + texImage3.hex = texUnit.texImage3[0].hex; + texTlut.hex = texUnit.texTlut[0].hex; + + int image_width = texImage0.width; + int image_height = texImage0.height; + + DebugUtil::GetTextureBGRA(temp, 0, 0, image_width, image_height); + + glGenTextures(1, (GLuint *)&texture); + glBindTexture(TEX2D, texture); +#ifdef USE_GLES + glTexImage2D(TEX2D, 0, GL_RGBA, (GLsizei)image_width, (GLsizei)image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); +#else + glTexImage2D(TEX2D, 0, GL_RGBA8, (GLsizei)image_width, (GLsizei)image_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp); +#endif + GL_REPORT_ERRORD(); + } + + void TexCacheEntry::Destroy() + { + if (texture == 0) + return; + + glDeleteTextures(1, &texture); + texture = 0; + } + + void TexCacheEntry::Update() + { + FourTexUnits &texUnit = bpmem.tex[0]; + + // extra checks cause textures to be reloaded much more + if (texUnit.texImage0[0].hex != texImage0.hex || + // texUnit.texImage1[0].hex != texImage1.hex || + // texUnit.texImage2[0].hex != texImage2.hex || + texUnit.texImage3[0].hex != texImage3.hex || + texUnit.texTlut[0].hex != texTlut.hex) + { + Destroy(); + Create(); + } + } +} + |
