Mercurial > sdl-ios-xcode
comparison src/video/SDL_renderer_gl.c @ 1927:aeb8263d377a
OpenGL renderer is feature complete!
Dynamically load GL functions in the OpenGL renderer.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 22 Jul 2006 23:04:41 +0000 |
parents | 307355678142 |
children | 861bc36f0ab3 |
comparison
equal
deleted
inserted
replaced
1926:307355678142 | 1927:aeb8263d377a |
---|---|
96 | 96 |
97 typedef struct | 97 typedef struct |
98 { | 98 { |
99 SDL_GLContext context; | 99 SDL_GLContext context; |
100 SDL_bool GL_ARB_texture_rectangle_supported; | 100 SDL_bool GL_ARB_texture_rectangle_supported; |
101 int blendMode; | |
102 int scaleMode; | |
103 | |
104 /* OpenGL functions */ | |
105 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params; | |
106 #include "SDL_glfuncs.h" | |
107 #undef SDL_PROC | |
101 } GL_RenderData; | 108 } GL_RenderData; |
102 | 109 |
103 typedef struct | 110 typedef struct |
104 { | 111 { |
105 GLuint texture; | 112 GLuint texture; |
147 default: | 154 default: |
148 error = "UNKNOWN"; | 155 error = "UNKNOWN"; |
149 break; | 156 break; |
150 } | 157 } |
151 SDL_SetError("%s: %s", prefix, error); | 158 SDL_SetError("%s: %s", prefix, error); |
159 } | |
160 | |
161 static int | |
162 GL_LoadFunctions(GL_RenderData * data) | |
163 { | |
164 #if defined(__QNXNTO__) && (_NTO_VERSION < 630) | |
165 #define __SDL_NOGETPROCADDR__ | |
166 #elif defined(__MINT__) | |
167 #define __SDL_NOGETPROCADDR__ | |
168 #endif | |
169 #ifdef __SDL_NOGETPROCADDR__ | |
170 #define SDL_PROC(ret,func,params) data->func=func; | |
171 #else | |
172 #define SDL_PROC(ret,func,params) \ | |
173 do { \ | |
174 data->func = SDL_GL_GetProcAddress(#func); \ | |
175 if ( ! data->func ) { \ | |
176 SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \ | |
177 return -1; \ | |
178 } \ | |
179 } while ( 0 ); | |
180 #endif /* __SDL_NOGETPROCADDR__ */ | |
181 | |
182 #include "SDL_glfuncs.h" | |
183 #undef SDL_PROC | |
184 return 0; | |
152 } | 185 } |
153 | 186 |
154 void | 187 void |
155 GL_AddRenderDriver(_THIS) | 188 GL_AddRenderDriver(_THIS) |
156 { | 189 { |
203 renderer->driverdata = data; | 236 renderer->driverdata = data; |
204 | 237 |
205 renderer->info.flags = | 238 renderer->info.flags = |
206 (SDL_Renderer_PresentDiscard | SDL_Renderer_Accelerated); | 239 (SDL_Renderer_PresentDiscard | SDL_Renderer_Accelerated); |
207 | 240 |
241 if (GL_LoadFunctions(data) < 0) { | |
242 GL_DestroyRenderer(renderer); | |
243 return NULL; | |
244 } | |
245 | |
208 data->context = SDL_GL_CreateContext(window->id); | 246 data->context = SDL_GL_CreateContext(window->id); |
209 if (!data->context) { | 247 if (!data->context) { |
210 GL_DestroyRenderer(renderer); | 248 GL_DestroyRenderer(renderer); |
211 return NULL; | 249 return NULL; |
212 } | 250 } |
222 } | 260 } |
223 if (SDL_GL_GetSwapInterval() > 0) { | 261 if (SDL_GL_GetSwapInterval() > 0) { |
224 renderer->info.flags |= SDL_Renderer_PresentVSync; | 262 renderer->info.flags |= SDL_Renderer_PresentVSync; |
225 } | 263 } |
226 | 264 |
227 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &renderer->info.max_texture_width); | 265 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, |
228 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &renderer->info.max_texture_height); | 266 &renderer->info.max_texture_width); |
267 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, | |
268 &renderer->info.max_texture_height); | |
229 | 269 |
230 if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") | 270 if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle") |
231 || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) { | 271 || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) { |
232 data->GL_ARB_texture_rectangle_supported = SDL_TRUE; | 272 data->GL_ARB_texture_rectangle_supported = SDL_TRUE; |
233 } | 273 } |
234 | 274 |
235 /* Set up parameters for rendering */ | 275 /* Set up parameters for rendering */ |
236 glDisable(GL_DEPTH_TEST); | 276 data->blendMode = -1; |
237 glDisable(GL_CULL_FACE); | 277 data->scaleMode = -1; |
278 data->glDisable(GL_DEPTH_TEST); | |
279 data->glDisable(GL_CULL_FACE); | |
238 if (data->GL_ARB_texture_rectangle_supported) { | 280 if (data->GL_ARB_texture_rectangle_supported) { |
239 glEnable(GL_TEXTURE_RECTANGLE_ARB); | 281 data->glEnable(GL_TEXTURE_RECTANGLE_ARB); |
240 } else { | 282 } else { |
241 glEnable(GL_TEXTURE_2D); | 283 data->glEnable(GL_TEXTURE_2D); |
242 } | 284 } |
243 glMatrixMode(GL_PROJECTION); | 285 data->glMatrixMode(GL_PROJECTION); |
244 glLoadIdentity(); | 286 data->glLoadIdentity(); |
245 glMatrixMode(GL_MODELVIEW); | 287 data->glMatrixMode(GL_MODELVIEW); |
246 glLoadIdentity(); | 288 data->glLoadIdentity(); |
247 glViewport(0, 0, window->w, window->h); | 289 data->glViewport(0, 0, window->w, window->h); |
248 glOrtho(0.0, (GLdouble) window->w, (GLdouble) window->h, 0.0, 0.0, 1.0); | 290 data->glOrtho(0.0, (GLdouble) window->w, (GLdouble) window->h, 0.0, 0.0, |
291 1.0); | |
249 | 292 |
250 return renderer; | 293 return renderer; |
251 } | 294 } |
252 | 295 |
253 static int | 296 static int |
369 return -1; | 412 return -1; |
370 } | 413 } |
371 | 414 |
372 texture->driverdata = data; | 415 texture->driverdata = data; |
373 | 416 |
374 glGetError(); | 417 renderdata->glGetError(); |
375 glGenTextures(1, &data->texture); | 418 renderdata->glGenTextures(1, &data->texture); |
376 if (renderdata->GL_ARB_texture_rectangle_supported) { | 419 if (renderdata->GL_ARB_texture_rectangle_supported) { |
377 data->type = GL_TEXTURE_RECTANGLE_ARB; | 420 data->type = GL_TEXTURE_RECTANGLE_ARB; |
378 texture_w = texture->w; | 421 texture_w = texture->w; |
379 texture_h = texture->h; | 422 texture_h = texture->h; |
380 data->texw = (GLfloat) texture->w; | 423 data->texw = (GLfloat) texture->w; |
386 data->texw = (GLfloat) texture->w / texture_w; | 429 data->texw = (GLfloat) texture->w / texture_w; |
387 data->texh = (GLfloat) texture->h / texture_h; | 430 data->texh = (GLfloat) texture->h / texture_h; |
388 } | 431 } |
389 data->format = format; | 432 data->format = format; |
390 data->formattype = type; | 433 data->formattype = type; |
391 glBindTexture(data->type, data->texture); | 434 renderdata->glBindTexture(data->type, data->texture); |
392 glTexImage2D(data->type, 0, internalFormat, texture_w, texture_h, 0, | 435 renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, |
393 format, type, NULL); | 436 texture_h, 0, format, type, NULL); |
394 result = glGetError(); | 437 result = renderdata->glGetError(); |
395 if (result != GL_NO_ERROR) { | 438 if (result != GL_NO_ERROR) { |
396 GL_SetError("glTexImage2D()", result); | 439 GL_SetError("glTexImage2D()", result); |
397 return -1; | 440 return -1; |
398 } | 441 } |
399 return 0; | 442 return 0; |
417 | 460 |
418 return 0; | 461 return 0; |
419 } | 462 } |
420 | 463 |
421 static void | 464 static void |
422 SetupTextureUpdate(SDL_Texture * texture, int pitch) | 465 SetupTextureUpdate(GL_RenderData * renderdata, SDL_Texture * texture, |
466 int pitch) | |
423 { | 467 { |
424 if (texture->format == SDL_PixelFormat_Index1LSB) { | 468 if (texture->format == SDL_PixelFormat_Index1LSB) { |
425 glPixelStorei(GL_UNPACK_LSB_FIRST, 1); | 469 renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 1); |
426 } else if (texture->format == SDL_PixelFormat_Index1MSB) { | 470 } else if (texture->format == SDL_PixelFormat_Index1MSB) { |
427 glPixelStorei(GL_UNPACK_LSB_FIRST, 0); | 471 renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 0); |
428 } | 472 } |
429 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | 473 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
430 glPixelStorei(GL_UNPACK_ROW_LENGTH, | 474 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, |
431 pitch / SDL_BYTESPERPIXEL(texture->format)); | 475 pitch / SDL_BYTESPERPIXEL(texture->format)); |
432 } | 476 } |
433 | 477 |
434 static int | 478 static int |
435 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, | 479 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, |
436 const SDL_Rect * rect, const void *pixels, int pitch) | 480 const SDL_Rect * rect, const void *pixels, int pitch) |
437 { | 481 { |
482 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; | |
438 GL_TextureData *data = (GL_TextureData *) texture->driverdata; | 483 GL_TextureData *data = (GL_TextureData *) texture->driverdata; |
439 GLenum result; | 484 GLenum result; |
440 | 485 |
441 glGetError(); | 486 renderdata->glGetError(); |
442 SetupTextureUpdate(texture, pitch); | 487 SetupTextureUpdate(renderdata, texture, pitch); |
443 glBindTexture(data->type, data->texture); | 488 renderdata->glBindTexture(data->type, data->texture); |
444 glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w, rect->h, | 489 renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w, |
445 data->format, data->formattype, pixels); | 490 rect->h, data->format, data->formattype, |
446 result = glGetError(); | 491 pixels); |
492 result = renderdata->glGetError(); | |
447 if (result != GL_NO_ERROR) { | 493 if (result != GL_NO_ERROR) { |
448 GL_SetError("glTexSubImage2D()", result); | 494 GL_SetError("glTexSubImage2D()", result); |
449 return -1; | 495 return -1; |
450 } | 496 } |
451 return 0; | 497 return 0; |
505 a = ((GLclampf) ((color >> 24) & 0xFF)) / 255.0f; | 551 a = ((GLclampf) ((color >> 24) & 0xFF)) / 255.0f; |
506 r = ((GLclampf) ((color >> 16) & 0xFF)) / 255.0f; | 552 r = ((GLclampf) ((color >> 16) & 0xFF)) / 255.0f; |
507 g = ((GLclampf) ((color >> 8) & 0xFF)) / 255.0f; | 553 g = ((GLclampf) ((color >> 8) & 0xFF)) / 255.0f; |
508 b = ((GLclampf) (color & 0xFF)) / 255.0f; | 554 b = ((GLclampf) (color & 0xFF)) / 255.0f; |
509 | 555 |
510 glClearColor(r, g, b, a); | 556 data->glClearColor(r, g, b, a); |
511 glViewport(rect->x, window->h - rect->y, rect->w, rect->h); | 557 data->glViewport(rect->x, window->h - rect->y, rect->w, rect->h); |
512 glClear(GL_COLOR_BUFFER_BIT); | 558 data->glClear(GL_COLOR_BUFFER_BIT); |
513 glViewport(0, 0, window->w, window->h); | 559 data->glViewport(0, 0, window->w, window->h); |
514 return 0; | 560 return 0; |
515 } | 561 } |
516 | 562 |
517 static int | 563 static int |
518 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | 564 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, |
528 SDL_DirtyRect *dirty; | 574 SDL_DirtyRect *dirty; |
529 void *pixels; | 575 void *pixels; |
530 int bpp = SDL_BYTESPERPIXEL(texture->format); | 576 int bpp = SDL_BYTESPERPIXEL(texture->format); |
531 int pitch = texturedata->pitch; | 577 int pitch = texturedata->pitch; |
532 | 578 |
533 SetupTextureUpdate(texture, pitch); | 579 SetupTextureUpdate(data, texture, pitch); |
534 glBindTexture(texturedata->type, texturedata->texture); | 580 data->glBindTexture(texturedata->type, texturedata->texture); |
535 for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) { | 581 for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) { |
536 SDL_Rect *rect = &dirty->rect; | 582 SDL_Rect *rect = &dirty->rect; |
537 pixels = | 583 pixels = |
538 (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch + | 584 (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch + |
539 rect->x * bpp); | 585 rect->x * bpp); |
540 glTexSubImage2D(texturedata->type, 0, rect->x, rect->y, rect->w, | 586 data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y, |
541 rect->h, texturedata->format, | 587 rect->w, rect->h, texturedata->format, |
542 texturedata->formattype, pixels); | 588 texturedata->formattype, pixels); |
543 } | 589 } |
544 SDL_ClearDirtyRects(&texturedata->dirty); | 590 SDL_ClearDirtyRects(&texturedata->dirty); |
545 } | 591 } |
546 | 592 |
547 minx = dstrect->x; | 593 minx = dstrect->x; |
556 minv = (GLfloat) srcrect->y / texture->h; | 602 minv = (GLfloat) srcrect->y / texture->h; |
557 minv *= texturedata->texh; | 603 minv *= texturedata->texh; |
558 maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; | 604 maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; |
559 maxv *= texturedata->texh; | 605 maxv *= texturedata->texh; |
560 | 606 |
561 glBindTexture(texturedata->type, texturedata->texture); | 607 data->glBindTexture(texturedata->type, texturedata->texture); |
562 | 608 |
563 switch (blendMode) { | 609 if (blendMode != data->blendMode) { |
564 case SDL_TextureBlendMode_None: | 610 switch (blendMode) { |
565 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); | 611 case SDL_TextureBlendMode_None: |
566 glDisable(GL_BLEND); | 612 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); |
567 break; | 613 data->glDisable(GL_BLEND); |
568 case SDL_TextureBlendMode_Mask: | 614 break; |
569 case SDL_TextureBlendMode_Blend: | 615 case SDL_TextureBlendMode_Mask: |
570 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | 616 case SDL_TextureBlendMode_Blend: |
571 glEnable(GL_BLEND); | 617 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
572 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 618 data->glEnable(GL_BLEND); |
573 break; | 619 data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
574 case SDL_TextureBlendMode_Add: | 620 break; |
575 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | 621 case SDL_TextureBlendMode_Add: |
576 glEnable(GL_BLEND); | 622 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
577 glBlendFunc(GL_SRC_ALPHA, GL_ONE); | 623 data->glEnable(GL_BLEND); |
578 break; | 624 data->glBlendFunc(GL_SRC_ALPHA, GL_ONE); |
579 case SDL_TextureBlendMode_Mod: | 625 break; |
580 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | 626 case SDL_TextureBlendMode_Mod: |
581 glEnable(GL_BLEND); | 627 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); |
582 glBlendFunc(GL_ZERO, GL_SRC_COLOR); | 628 data->glEnable(GL_BLEND); |
583 break; | 629 data->glBlendFunc(GL_ZERO, GL_SRC_COLOR); |
584 } | 630 break; |
585 | 631 } |
586 switch (scaleMode) { | 632 data->blendMode = blendMode; |
587 case SDL_TextureScaleMode_None: | 633 } |
588 case SDL_TextureScaleMode_Fast: | 634 |
589 glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 635 if (scaleMode != data->scaleMode) { |
590 glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 636 switch (scaleMode) { |
591 break; | 637 case SDL_TextureScaleMode_None: |
592 case SDL_TextureScaleMode_Slow: | 638 case SDL_TextureScaleMode_Fast: |
593 case SDL_TextureScaleMode_Best: | 639 data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, |
594 glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 640 GL_NEAREST); |
595 glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 641 data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, |
596 break; | 642 GL_NEAREST); |
597 } | 643 break; |
598 | 644 case SDL_TextureScaleMode_Slow: |
599 glBegin(GL_TRIANGLE_STRIP); | 645 case SDL_TextureScaleMode_Best: |
600 glTexCoord2f(minu, minv); | 646 data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER, |
601 glVertex2i(minx, miny); | 647 GL_LINEAR); |
602 glTexCoord2f(maxu, minv); | 648 data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER, |
603 glVertex2i(maxx, miny); | 649 GL_LINEAR); |
604 glTexCoord2f(minu, maxv); | 650 break; |
605 glVertex2i(minx, maxy); | 651 } |
606 glTexCoord2f(maxu, maxv); | 652 data->scaleMode = scaleMode; |
607 glVertex2i(maxx, maxy); | 653 } |
608 glEnd(); | 654 |
655 data->glBegin(GL_TRIANGLE_STRIP); | |
656 data->glTexCoord2f(minu, minv); | |
657 data->glVertex2i(minx, miny); | |
658 data->glTexCoord2f(maxu, minv); | |
659 data->glVertex2i(maxx, miny); | |
660 data->glTexCoord2f(minu, maxv); | |
661 data->glVertex2i(minx, maxy); | |
662 data->glTexCoord2f(maxu, maxv); | |
663 data->glVertex2i(maxx, maxy); | |
664 data->glEnd(); | |
609 | 665 |
610 return 0; | 666 return 0; |
611 } | 667 } |
612 | 668 |
613 static void | 669 static void |
617 } | 673 } |
618 | 674 |
619 static void | 675 static void |
620 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | 676 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) |
621 { | 677 { |
678 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; | |
622 GL_TextureData *data = (GL_TextureData *) texture->driverdata; | 679 GL_TextureData *data = (GL_TextureData *) texture->driverdata; |
623 | 680 |
624 if (!data) { | 681 if (!data) { |
625 return; | 682 return; |
626 } | 683 } |
627 if (data->texture) { | 684 if (data->texture) { |
628 glDeleteTextures(1, &data->texture); | 685 renderdata->glDeleteTextures(1, &data->texture); |
629 } | 686 } |
630 if (data->pixels) { | 687 if (data->pixels) { |
631 SDL_free(data->pixels); | 688 SDL_free(data->pixels); |
632 } | 689 } |
633 SDL_FreeDirtyRects(&data->dirty); | 690 SDL_FreeDirtyRects(&data->dirty); |