Mercurial > sdl-ios-xcode
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 |