comparison src/video/SDL_renderer_gl.c @ 3468:789b97008d8a

My first OpenGL shader! Momma will be so proud! This shader implements the software renderer mask semantics where the source pixel is multiplied by the color and alpha modulation values and then any pixel with non-zero alpha is fully opaque. The OpenGL renderer on Mac OS X now passes all the automated render tests! :)
author Sam Lantinga <slouken@libsdl.org>
date Sat, 21 Nov 2009 05:29:31 +0000
parents 0aed0755d1f1
children 419f459f2f38
comparison
equal deleted inserted replaced
3467:383c2058d973 3468:789b97008d8a
173 PFNGLGENPROGRAMSARBPROC glGenProgramsARB; 173 PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
174 PFNGLBINDPROGRAMARBPROC glBindProgramARB; 174 PFNGLBINDPROGRAMARBPROC glBindProgramARB;
175 PFNGLPROGRAMSTRINGARBPROC glProgramStringARB; 175 PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
176 176
177 /* (optional) fragment programs */ 177 /* (optional) fragment programs */
178 GLuint fragment_program_mask;
178 GLuint fragment_program_UYVY; 179 GLuint fragment_program_UYVY;
179 } GL_RenderData; 180 } GL_RenderData;
180 181
181 typedef struct 182 typedef struct
182 { 183 {
482 } 483 }
483 484
484 485
485 //#define DEBUG_PROGRAM_COMPILE 1 486 //#define DEBUG_PROGRAM_COMPILE 1
486 487
488 static void
489 set_shader_error(GL_RenderData * data, const char *prefix)
490 {
491 GLint pos = 0;
492 const GLubyte *errstr;
493 data->glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
494 errstr = data->glGetString(GL_PROGRAM_ERROR_STRING_ARB);
495 printf("%s: shader compile error at position %d: %s",
496 prefix, (int) pos, (const char *) errstr);
497 }
498
487 static GLuint 499 static GLuint
488 compile_shader(GL_RenderData * data, GLenum shader_type, const char *_code) 500 compile_shader(GL_RenderData * data, GLenum shader_type, const char *_code)
489 { 501 {
490 const int have_texture_rects = data->GL_ARB_texture_rectangle_supported; 502 const int have_texture_rects = data->GL_ARB_texture_rectangle_supported;
491 const char *replacement = have_texture_rects ? "RECT" : "2D"; 503 const char *replacement = have_texture_rects ? "RECT" : "2D";
538 } 550 }
539 551
540 return program; 552 return program;
541 } 553 }
542 554
555
556 /*
557 * Fragment program that implements mask semantics
558 */
559 static const char *fragment_program_mask_source_code = "!!ARBfp1.0\n"
560 "OUTPUT output = result.color;\n"
561 "TEMP value;\n"
562 "TEX value, fragment.texcoord[0], texture[0], %TEXTURETARGET%;\n"
563 "MUL value, fragment.color, value;\n"
564 "SGE value.a, value.a, 0.001;\n"
565 "MOV output, value;\n"
566 "END";
543 567
544 /* 568 /*
545 * Fragment program that renders from UYVY textures. 569 * Fragment program that renders from UYVY textures.
546 * The UYVY to RGB equasion is: 570 * The UYVY to RGB equasion is:
547 * R = 1.164(Y-16) + 1.596(Cr-128) 571 * R = 1.164(Y-16) + 1.596(Cr-128)
749 if (renderdata->fragment_program_UYVY == 0) { 773 if (renderdata->fragment_program_UYVY == 0) {
750 renderdata->fragment_program_UYVY = 774 renderdata->fragment_program_UYVY =
751 compile_shader(renderdata, GL_FRAGMENT_PROGRAM_ARB, 775 compile_shader(renderdata, GL_FRAGMENT_PROGRAM_ARB,
752 fragment_program_UYVY_source_code); 776 fragment_program_UYVY_source_code);
753 if (renderdata->fragment_program_UYVY == 0) { 777 if (renderdata->fragment_program_UYVY == 0) {
754 SDL_SetError("Fragment program compile error"); 778 set_shader_error(renderdata, "UYVY");
755 return -1; 779 return -1;
756 } 780 }
757 } 781 }
758 shader = renderdata->fragment_program_UYVY; 782 shader = renderdata->fragment_program_UYVY;
759 } 783 }
1160 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 1184 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
1161 const SDL_Rect * srcrect, const SDL_Rect * dstrect) 1185 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
1162 { 1186 {
1163 GL_RenderData *data = (GL_RenderData *) renderer->driverdata; 1187 GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
1164 GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata; 1188 GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
1189 GLuint shader = 0;
1165 int minx, miny, maxx, maxy; 1190 int minx, miny, maxx, maxy;
1166 GLfloat minu, maxu, minv, maxv; 1191 GLfloat minu, maxu, minv, maxv;
1167 1192
1168 if (texturedata->dirty.list) { 1193 if (texturedata->dirty.list) {
1169 SDL_DirtyRect *dirty; 1194 SDL_DirtyRect *dirty;
1212 } else { 1237 } else {
1213 data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 1238 data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1214 } 1239 }
1215 1240
1216 GL_SetBlendMode(data, texture->blendMode, 0); 1241 GL_SetBlendMode(data, texture->blendMode, 0);
1242
1243 /* Set up the shader for the copy, we have a special one for MASK */
1244 shader = texturedata->shader;
1245 if (texture->blendMode == SDL_BLENDMODE_MASK && !shader) {
1246 if (data->fragment_program_mask == 0) {
1247 data->fragment_program_mask =
1248 compile_shader(data, GL_FRAGMENT_PROGRAM_ARB,
1249 fragment_program_mask_source_code);
1250 if (data->fragment_program_mask == 0) {
1251 /* That's okay, we'll just miss some of the blend semantics */
1252 data->fragment_program_mask = ~0;
1253 }
1254 }
1255 if (data->fragment_program_mask != ~0) {
1256 shader = data->fragment_program_mask;
1257 }
1258 }
1217 1259
1218 if (texture->scaleMode != data->scaleMode) { 1260 if (texture->scaleMode != data->scaleMode) {
1219 switch (texture->scaleMode) { 1261 switch (texture->scaleMode) {
1220 case SDL_TEXTURESCALEMODE_NONE: 1262 case SDL_TEXTURESCALEMODE_NONE:
1221 case SDL_TEXTURESCALEMODE_FAST: 1263 case SDL_TEXTURESCALEMODE_FAST:
1233 break; 1275 break;
1234 } 1276 }
1235 data->scaleMode = texture->scaleMode; 1277 data->scaleMode = texture->scaleMode;
1236 } 1278 }
1237 1279
1238 if (texturedata->shader != 0) { 1280 if (shader) {
1239 data->glEnable(GL_FRAGMENT_PROGRAM_ARB); 1281 data->glEnable(GL_FRAGMENT_PROGRAM_ARB);
1240 data->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, texturedata->shader); 1282 data->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader);
1241 } 1283 }
1242 1284
1243 data->glBegin(GL_TRIANGLE_STRIP); 1285 data->glBegin(GL_TRIANGLE_STRIP);
1244 data->glTexCoord2f(minu, minv); 1286 data->glTexCoord2f(minu, minv);
1245 data->glVertex2f(0.5f + minx, 0.5f + miny); 1287 data->glVertex2f(0.5f + minx, 0.5f + miny);
1249 data->glVertex2f(0.5f + minx, 0.5f + maxy); 1291 data->glVertex2f(0.5f + minx, 0.5f + maxy);
1250 data->glTexCoord2f(maxu, maxv); 1292 data->glTexCoord2f(maxu, maxv);
1251 data->glVertex2f(0.5f + maxx, 0.5f + maxy); 1293 data->glVertex2f(0.5f + maxx, 0.5f + maxy);
1252 data->glEnd(); 1294 data->glEnd();
1253 1295
1254 if (texturedata->shader != 0) { 1296 if (shader) {
1255 data->glDisable(GL_FRAGMENT_PROGRAM_ARB); 1297 data->glDisable(GL_FRAGMENT_PROGRAM_ARB);
1256 } 1298 }
1257 1299
1258 data->glDisable(texturedata->type); 1300 data->glDisable(texturedata->type);
1259 1301
1375 if (data) { 1417 if (data) {
1376 if (data->context) { 1418 if (data->context) {
1377 if (data->GL_ARB_fragment_program_supported) { 1419 if (data->GL_ARB_fragment_program_supported) {
1378 data->glDisable(GL_FRAGMENT_PROGRAM_ARB); 1420 data->glDisable(GL_FRAGMENT_PROGRAM_ARB);
1379 data->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0); 1421 data->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
1380 if (data->fragment_program_UYVY != 0) { 1422 if (data->fragment_program_mask &&
1423 data->fragment_program_mask != ~0) {
1424 data->glDeleteProgramsARB(1,
1425 &data->fragment_program_mask);
1426 }
1427 if (data->fragment_program_UYVY &&
1428 data->fragment_program_UYVY != ~0) {
1381 data->glDeleteProgramsARB(1, 1429 data->glDeleteProgramsARB(1,
1382 &data->fragment_program_UYVY); 1430 &data->fragment_program_UYVY);
1383 } 1431 }
1384 } 1432 }
1385 1433