1
// Copyright 2013 Dolphin Emulator Project
2
// Licensed under GPLv2
3
// Refer to the license.txt file included.
6
#include "MemoryUtil.h"
8
#include <VideoCommon.h>
10
#include "BPMemLoader.h"
11
#include "HwRasterizer.h"
12
#include "NativeVertexFormat.h"
13
#include "DebugUtil.h"
15
#define TEMP_SIZE (1024*1024*4)
17
namespace HwRasterizer
26
static GLuint colProg, texProg, clearProg;
29
static GLint col_apos = -1, col_atex = -1;
31
static GLint tex_apos = -1, tex_atex = -1, tex_utex = -1;
33
static GLint clear_apos = -1, clear_ucol = -1;
38
static const char *fragcolText =
39
"varying " PREC " vec4 TexCoordOut;\n"
41
" gl_FragColor = TexCoordOut;\n"
44
static const char *fragtexText =
45
"varying " PREC " vec4 TexCoordOut;\n"
46
"uniform " TEXTYPE " Texture;\n"
48
" gl_FragColor = " TEXFUNC "(Texture, TexCoordOut.xy);\n"
51
static const char *fragclearText =
52
"uniform " PREC " vec4 Color;\n"
54
" gl_FragColor = Color;\n"
56
// Generic passthrough vertice shaders
57
static const char *vertShaderText =
58
"attribute vec4 pos;\n"
59
"attribute vec4 TexCoordIn;\n "
60
"varying vec4 TexCoordOut;\n "
62
" gl_Position = pos;\n"
63
" TexCoordOut = TexCoordIn;\n"
65
static const char *vertclearText =
66
"attribute vec4 pos;\n"
68
" gl_Position = pos;\n"
72
colProg = OpenGL_CompileProgram(vertShaderText, fragcolText);
75
texProg = OpenGL_CompileProgram(vertShaderText, fragtexText);
78
clearProg = OpenGL_CompileProgram(vertclearText, fragclearText);
81
col_apos = glGetAttribLocation(colProg, "pos");
82
col_atex = glGetAttribLocation(colProg, "TexCoordIn");
84
tex_apos = glGetAttribLocation(texProg, "pos");
85
tex_atex = glGetAttribLocation(texProg, "TexCoordIn");
86
tex_utex = glGetUniformLocation(texProg, "Texture");
88
clear_apos = glGetAttribLocation(clearProg, "pos");
89
clear_ucol = glGetUniformLocation(clearProg, "Color");
94
efbHalfWidth = EFB_WIDTH / 2.0f;
95
efbHalfHeight = 480 / 2.0f;
97
temp = (u8*)AllocateMemoryPages(TEMP_SIZE);
101
glDeleteProgram(colProg);
102
glDeleteProgram(texProg);
103
glDeleteProgram(clearProg);
107
//legacy multitexturing: select texture channel only.
108
glActiveTexture(GL_TEXTURE0);
109
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment
111
glShadeModel(GL_SMOOTH);
114
glEnable(GL_SCISSOR_TEST);
115
glDisable(GL_LIGHTING);
116
glMatrixMode(GL_PROJECTION);
118
glMatrixMode(GL_MODELVIEW);
121
glClientActiveTexture(GL_TEXTURE0);
122
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
123
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
124
glEnable(GL_TEXTURE_RECTANGLE_ARB);
125
glStencilFunc(GL_ALWAYS, 0, 0);
126
glDisable(GL_STENCIL_TEST);
128
// used by hw rasterizer if it enables blending and depth test
129
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
130
glDepthFunc(GL_LEQUAL);
132
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
137
static float width, height;
140
FourTexUnits &texUnit = bpmem.tex[0];
141
u32 imageAddr = texUnit.texImage3[0].image_base;
142
// Texture Rectangle uses pixel coordinates
143
// While GLES uses texture coordinates
145
width = texUnit.texImage0[0].width;
146
height = texUnit.texImage0[0].height;
151
TexCacheEntry &cacheEntry = textures[imageAddr];
154
glBindTexture(TEX2D, cacheEntry.texture);
155
glTexParameteri(TEX2D, GL_TEXTURE_MAG_FILTER, texUnit.texMode0[0].mag_filter ? GL_LINEAR : GL_NEAREST);
156
glTexParameteri(TEX2D, GL_TEXTURE_MIN_FILTER, (texUnit.texMode0[0].min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
160
void BeginTriangles()
162
// disabling depth test sometimes allows more things to be visible
163
glEnable(GL_DEPTH_TEST);
166
hasTexture = bpmem.tevorders[0].enable0;
174
glBindTexture(TEX2D, 0);
175
glDisable(GL_DEPTH_TEST);
179
void DrawColorVertex(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
181
float x0 = (v0->screenPosition.x / efbHalfWidth) - 1.0f;
182
float y0 = 1.0f - (v0->screenPosition.y / efbHalfHeight);
183
float z0 = v0->screenPosition.z / (float)0x00ffffff;
185
float x1 = (v1->screenPosition.x / efbHalfWidth) - 1.0f;
186
float y1 = 1.0f - (v1->screenPosition.y / efbHalfHeight);
187
float z1 = v1->screenPosition.z / (float)0x00ffffff;
189
float x2 = (v2->screenPosition.x / efbHalfWidth) - 1.0f;
190
float y2 = 1.0f - (v2->screenPosition.y / efbHalfHeight);
191
float z2 = v2->screenPosition.z / (float)0x00ffffff;
193
float r0 = v0->color[0][OutputVertexData::RED_C] / 255.0f;
194
float g0 = v0->color[0][OutputVertexData::GRN_C] / 255.0f;
195
float b0 = v0->color[0][OutputVertexData::BLU_C] / 255.0f;
197
float r1 = v1->color[0][OutputVertexData::RED_C] / 255.0f;
198
float g1 = v1->color[0][OutputVertexData::GRN_C] / 255.0f;
199
float b1 = v1->color[0][OutputVertexData::BLU_C] / 255.0f;
201
float r2 = v2->color[0][OutputVertexData::RED_C] / 255.0f;
202
float g2 = v2->color[0][OutputVertexData::GRN_C] / 255.0f;
203
float b2 = v2->color[0][OutputVertexData::BLU_C] / 255.0f;
205
static const GLfloat verts[3][3] = {
210
static const GLfloat col[3][4] = {
211
{ r0, g0, b0, 1.0f },
212
{ r1, g1, b1, 1.0f },
216
glUseProgram(colProg);
217
glEnableVertexAttribArray(col_apos);
218
glEnableVertexAttribArray(col_atex);
220
glVertexAttribPointer(col_apos, 3, GL_FLOAT, GL_FALSE, 0, verts);
221
glVertexAttribPointer(col_atex, 4, GL_FLOAT, GL_FALSE, 0, col);
222
glDrawArrays(GL_TRIANGLES, 0, 3);
223
glDisableVertexAttribArray(col_atex);
224
glDisableVertexAttribArray(col_apos);
229
void DrawTextureVertex(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
231
float x0 = (v0->screenPosition.x / efbHalfWidth) - 1.0f;
232
float y0 = 1.0f - (v0->screenPosition.y / efbHalfHeight);
233
float z0 = v0->screenPosition.z;
235
float x1 = (v1->screenPosition.x / efbHalfWidth) - 1.0f;
236
float y1 = 1.0f - (v1->screenPosition.y / efbHalfHeight);
237
float z1 = v1->screenPosition.z;
239
float x2 = (v2->screenPosition.x / efbHalfWidth) - 1.0f;
240
float y2 = 1.0f - (v2->screenPosition.y / efbHalfHeight);
241
float z2 = v2->screenPosition.z;
243
float s0 = v0->texCoords[0].x / width;
244
float t0 = v0->texCoords[0].y / height;
246
float s1 = v1->texCoords[0].x / width;
247
float t1 = v1->texCoords[0].y / height;
249
float s2 = v2->texCoords[0].x / width;
250
float t2 = v2->texCoords[0].y / height;
252
static const GLfloat verts[3][3] = {
257
static const GLfloat tex[3][2] = {
263
glUseProgram(texProg);
264
glEnableVertexAttribArray(tex_apos);
265
glEnableVertexAttribArray(tex_atex);
267
glVertexAttribPointer(tex_apos, 3, GL_FLOAT, GL_FALSE, 0, verts);
268
glVertexAttribPointer(tex_atex, 2, GL_FLOAT, GL_FALSE, 0, tex);
269
glUniform1i(tex_utex, 0);
270
glDrawArrays(GL_TRIANGLES, 0, 3);
271
glDisableVertexAttribArray(tex_atex);
272
glDisableVertexAttribArray(tex_apos);
277
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
280
DrawTextureVertex(v0, v1, v2);
282
DrawColorVertex(v0, v1, v2);
287
u8 r = (bpmem.clearcolorAR & 0x00ff);
288
u8 g = (bpmem.clearcolorGB & 0xff00) >> 8;
289
u8 b = (bpmem.clearcolorGB & 0x00ff);
290
u8 a = (bpmem.clearcolorAR & 0xff00) >> 8;
292
GLfloat left = (GLfloat)bpmem.copyTexSrcXY.x / efbHalfWidth - 1.0f;
293
GLfloat top = 1.0f - (GLfloat)bpmem.copyTexSrcXY.y / efbHalfHeight;
294
GLfloat right = (GLfloat)(left + bpmem.copyTexSrcWH.x + 1) / efbHalfWidth - 1.0f;
295
GLfloat bottom = 1.0f - (GLfloat)(top + bpmem.copyTexSrcWH.y + 1) / efbHalfHeight;
296
GLfloat depth = (GLfloat)bpmem.clearZValue / (GLfloat)0x00ffffff;
297
static const GLfloat verts[4][3] = {
298
{ left, top, depth },
299
{ right, top, depth },
300
{ right, bottom, depth },
301
{ left, bottom, depth }
304
glUseProgram(clearProg);
305
glVertexAttribPointer(clear_apos, 3, GL_FLOAT, GL_FALSE, 0, verts);
306
glUniform4f(clear_ucol, r, g, b, a);
307
glEnableVertexAttribArray(col_apos);
308
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
309
glDisableVertexAttribArray(col_apos);
314
TexCacheEntry::TexCacheEntry()
319
void TexCacheEntry::Create()
321
FourTexUnits &texUnit = bpmem.tex[0];
323
texImage0.hex = texUnit.texImage0[0].hex;
324
texImage1.hex = texUnit.texImage1[0].hex;
325
texImage2.hex = texUnit.texImage2[0].hex;
326
texImage3.hex = texUnit.texImage3[0].hex;
327
texTlut.hex = texUnit.texTlut[0].hex;
329
int image_width = texImage0.width;
330
int image_height = texImage0.height;
332
DebugUtil::GetTextureBGRA(temp, 0, 0, image_width, image_height);
334
glGenTextures(1, (GLuint *)&texture);
335
glBindTexture(TEX2D, texture);
337
glTexImage2D(TEX2D, 0, GL_RGBA, (GLsizei)image_width, (GLsizei)image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp);
339
glTexImage2D(TEX2D, 0, GL_RGBA8, (GLsizei)image_width, (GLsizei)image_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp);
344
void TexCacheEntry::Destroy()
349
glDeleteTextures(1, &texture);
353
void TexCacheEntry::Update()
355
FourTexUnits &texUnit = bpmem.tex[0];
357
// extra checks cause textures to be reloaded much more
358
if (texUnit.texImage0[0].hex != texImage0.hex ||
359
// texUnit.texImage1[0].hex != texImage1.hex ||
360
// texUnit.texImage2[0].hex != texImage2.hex ||
361
texUnit.texImage3[0].hex != texImage3.hex ||
362
texUnit.texTlut[0].hex != texTlut.hex)