148 GLuint vtexture; |
148 GLuint vtexture; |
149 |
149 |
150 GL_FBOList *fbo; |
150 GL_FBOList *fbo; |
151 } GL_TextureData; |
151 } GL_TextureData; |
152 |
152 |
153 |
153 static inline const char* |
154 static void |
154 GL_TranslateError (GLenum error) |
155 GL_SetError(const char *prefix, GLenum result) |
155 { |
156 { |
156 #define GL_ERROR_TRANSLATE(e) case e: return #e; |
157 const char *error; |
157 switch (error) { |
158 |
158 GL_ERROR_TRANSLATE(GL_INVALID_ENUM) |
159 switch (result) { |
159 GL_ERROR_TRANSLATE(GL_INVALID_VALUE) |
160 case GL_NO_ERROR: |
160 GL_ERROR_TRANSLATE(GL_INVALID_OPERATION) |
161 error = "GL_NO_ERROR"; |
161 GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY) |
162 break; |
162 GL_ERROR_TRANSLATE(GL_NO_ERROR) |
163 case GL_INVALID_ENUM: |
163 GL_ERROR_TRANSLATE(GL_STACK_OVERFLOW) |
164 error = "GL_INVALID_ENUM"; |
164 GL_ERROR_TRANSLATE(GL_STACK_UNDERFLOW) |
165 break; |
165 GL_ERROR_TRANSLATE(GL_TABLE_TOO_LARGE) |
166 case GL_INVALID_VALUE: |
|
167 error = "GL_INVALID_VALUE"; |
|
168 break; |
|
169 case GL_INVALID_OPERATION: |
|
170 error = "GL_INVALID_OPERATION"; |
|
171 break; |
|
172 case GL_STACK_OVERFLOW: |
|
173 error = "GL_STACK_OVERFLOW"; |
|
174 break; |
|
175 case GL_STACK_UNDERFLOW: |
|
176 error = "GL_STACK_UNDERFLOW"; |
|
177 break; |
|
178 case GL_OUT_OF_MEMORY: |
|
179 error = "GL_OUT_OF_MEMORY"; |
|
180 break; |
|
181 case GL_TABLE_TOO_LARGE: |
|
182 error = "GL_TABLE_TOO_LARGE"; |
|
183 break; |
|
184 default: |
166 default: |
185 error = "UNKNOWN"; |
167 return "UNKNOWN"; |
186 break; |
168 } |
187 } |
169 #undef GL_ERROR_TRANSLATE |
188 SDL_SetError("%s: %s", prefix, error); |
170 } |
189 } |
171 |
|
172 static __inline__ int |
|
173 GL_CheckAllErrors (const char *prefix, SDL_Renderer * renderer, const char *file, int line, const char *function) |
|
174 { |
|
175 GL_RenderData *data = (GL_RenderData *) renderer->driverdata; |
|
176 int ret = 0; |
|
177 /* check gl errors (can return multiple errors) */ |
|
178 for (;;) { |
|
179 GLenum error = data->glGetError(); |
|
180 if (error != GL_NO_ERROR) { |
|
181 if (prefix == NULL || prefix[0] == '\0') { |
|
182 prefix = "generic"; |
|
183 } |
|
184 SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error); |
|
185 ret++; |
|
186 } else { |
|
187 break; |
|
188 } |
|
189 } |
|
190 return ret; |
|
191 } |
|
192 |
|
193 #if 1 |
|
194 #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, __FILE__, __LINE__, __PRETTY_FUNCTION__) |
|
195 #else |
|
196 #define GL_CheckError(prefix, renderer) |
|
197 #endif |
190 |
198 |
191 static int |
199 static int |
192 GL_LoadFunctions(GL_RenderData * data) |
200 GL_LoadFunctions(GL_RenderData * data) |
193 { |
201 { |
194 #ifdef __SDL_NOGETPROCADDR__ |
202 #ifdef __SDL_NOGETPROCADDR__ |
248 /* This ended up causing video discrepancies between OpenGL and Direct3D */ |
256 /* This ended up causing video discrepancies between OpenGL and Direct3D */ |
249 /*data->glEnable(GL_LINE_SMOOTH);*/ |
257 /*data->glEnable(GL_LINE_SMOOTH);*/ |
250 |
258 |
251 data->glMatrixMode(GL_MODELVIEW); |
259 data->glMatrixMode(GL_MODELVIEW); |
252 data->glLoadIdentity(); |
260 data->glLoadIdentity(); |
|
261 |
|
262 GL_CheckError("", renderer); |
253 } |
263 } |
254 |
264 |
255 |
265 |
256 GL_FBOList * |
266 GL_FBOList * |
257 GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h) |
267 GL_GetFBO(GL_RenderData *data, Uint32 w, Uint32 h) |
481 GL_TextureData *data; |
491 GL_TextureData *data; |
482 GLint internalFormat; |
492 GLint internalFormat; |
483 GLenum format, type; |
493 GLenum format, type; |
484 int texture_w, texture_h; |
494 int texture_w, texture_h; |
485 GLenum scaleMode; |
495 GLenum scaleMode; |
486 GLenum result; |
|
487 |
496 |
488 GL_ActivateRenderer(renderer); |
497 GL_ActivateRenderer(renderer); |
489 |
498 |
490 if (!convert_format(renderdata, texture->format, &internalFormat, |
499 if (!convert_format(renderdata, texture->format, &internalFormat, |
491 &format, &type)) { |
500 &format, &type)) { |
523 data->fbo = GL_GetFBO(renderdata, texture->w, texture->h); |
532 data->fbo = GL_GetFBO(renderdata, texture->w, texture->h); |
524 } else { |
533 } else { |
525 data->fbo = NULL; |
534 data->fbo = NULL; |
526 } |
535 } |
527 |
536 |
528 renderdata->glGetError(); |
537 GL_CheckError("", renderer); |
529 renderdata->glGenTextures(1, &data->texture); |
538 renderdata->glGenTextures(1, &data->texture); |
530 if ((renderdata->GL_ARB_texture_rectangle_supported) |
539 if ((renderdata->GL_ARB_texture_rectangle_supported) |
531 /*&& texture->access != SDL_TEXTUREACCESS_TARGET*/){ |
540 /*&& texture->access != SDL_TEXTUREACCESS_TARGET*/){ |
532 data->type = GL_TEXTURE_RECTANGLE_ARB; |
541 data->type = GL_TEXTURE_RECTANGLE_ARB; |
533 texture_w = texture->w; |
542 texture_w = texture->w; |
591 { |
600 { |
592 renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, |
601 renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, |
593 texture_h, 0, format, type, NULL); |
602 texture_h, 0, format, type, NULL); |
594 } |
603 } |
595 renderdata->glDisable(data->type); |
604 renderdata->glDisable(data->type); |
596 result = renderdata->glGetError(); |
605 if (GL_CheckError("glTexImage2D()", renderer) > 0) { |
597 if (result != GL_NO_ERROR) { |
|
598 GL_SetError("glTexImage2D()", result); |
|
599 return -1; |
606 return -1; |
600 } |
607 } |
601 |
608 |
602 if (texture->format == SDL_PIXELFORMAT_YV12 || |
609 if (texture->format == SDL_PIXELFORMAT_YV12 || |
603 texture->format == SDL_PIXELFORMAT_IYUV) { |
610 texture->format == SDL_PIXELFORMAT_IYUV) { |
631 renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2, |
638 renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2, |
632 texture_h/2, 0, format, type, NULL); |
639 texture_h/2, 0, format, type, NULL); |
633 |
640 |
634 renderdata->glDisable(data->type); |
641 renderdata->glDisable(data->type); |
635 } |
642 } |
|
643 |
|
644 GL_CheckError("", renderer); |
636 return 0; |
645 return 0; |
637 } |
646 } |
638 |
647 |
639 static int |
648 static int |
640 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, |
649 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, |
641 const SDL_Rect * rect, const void *pixels, int pitch) |
650 const SDL_Rect * rect, const void *pixels, int pitch) |
642 { |
651 { |
643 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; |
652 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata; |
644 GL_TextureData *data = (GL_TextureData *) texture->driverdata; |
653 GL_TextureData *data = (GL_TextureData *) texture->driverdata; |
645 GLenum result; |
|
646 |
654 |
647 GL_ActivateRenderer(renderer); |
655 GL_ActivateRenderer(renderer); |
648 |
656 |
649 renderdata->glGetError(); |
657 GL_CheckError("", renderer); |
650 renderdata->glEnable(data->type); |
658 renderdata->glEnable(data->type); |
651 renderdata->glBindTexture(data->type, data->texture); |
659 renderdata->glBindTexture(data->type, data->texture); |
652 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
660 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
653 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, |
661 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, |
654 (pitch / SDL_BYTESPERPIXEL(texture->format))); |
662 (pitch / SDL_BYTESPERPIXEL(texture->format))); |
679 renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2, |
687 renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2, |
680 rect->w/2, rect->h/2, |
688 rect->w/2, rect->h/2, |
681 data->format, data->formattype, pixels); |
689 data->format, data->formattype, pixels); |
682 } |
690 } |
683 renderdata->glDisable(data->type); |
691 renderdata->glDisable(data->type); |
684 result = renderdata->glGetError(); |
692 if (GL_CheckError("glTexSubImage2D()", renderer) > 0) { |
685 if (result != GL_NO_ERROR) { |
|
686 GL_SetError("glTexSubImage2D()", result); |
|
687 return -1; |
693 return -1; |
688 } |
694 } |
689 return 0; |
695 return 0; |
690 } |
696 } |
691 |
697 |
750 GL_RenderData *data = (GL_RenderData *) renderer->driverdata; |
756 GL_RenderData *data = (GL_RenderData *) renderer->driverdata; |
751 |
757 |
752 if (SDL_CurrentContext != data->context) { |
758 if (SDL_CurrentContext != data->context) { |
753 /* We'll update the viewport after we rebind the context */ |
759 /* We'll update the viewport after we rebind the context */ |
754 return 0; |
760 return 0; |
|
761 } |
|
762 |
|
763 if (!renderer->viewport.w || !renderer->viewport.h) { |
|
764 /* The viewport isn't set up yet, ignore it */ |
|
765 return -1; |
755 } |
766 } |
756 |
767 |
757 data->glViewport(renderer->viewport.x, renderer->viewport.y, |
768 data->glViewport(renderer->viewport.x, renderer->viewport.y, |
758 renderer->viewport.w, renderer->viewport.h); |
769 renderer->viewport.w, renderer->viewport.h); |
759 |
770 |
1149 data->glPixelStorei(GL_PACK_ROW_LENGTH, |
1167 data->glPixelStorei(GL_PACK_ROW_LENGTH, |
1150 (temp_pitch / SDL_BYTESPERPIXEL(temp_format))); |
1168 (temp_pitch / SDL_BYTESPERPIXEL(temp_format))); |
1151 |
1169 |
1152 data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h, |
1170 data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h, |
1153 format, type, temp_pixels); |
1171 format, type, temp_pixels); |
|
1172 |
|
1173 GL_CheckError("", renderer); |
1154 |
1174 |
1155 /* Flip the rows to be top-down */ |
1175 /* Flip the rows to be top-down */ |
1156 length = rect->w * SDL_BYTESPERPIXEL(temp_format); |
1176 length = rect->w * SDL_BYTESPERPIXEL(temp_format); |
1157 src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch; |
1177 src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch; |
1158 dst = (Uint8*)temp_pixels; |
1178 dst = (Uint8*)temp_pixels; |
1220 if (data->context) { |
1240 if (data->context) { |
1221 while (data->framebuffers) { |
1241 while (data->framebuffers) { |
1222 GL_FBOList *nextnode = data->framebuffers->next; |
1242 GL_FBOList *nextnode = data->framebuffers->next; |
1223 /* delete the framebuffer object */ |
1243 /* delete the framebuffer object */ |
1224 data->glDeleteFramebuffersEXT(1, &data->framebuffers->FBO); |
1244 data->glDeleteFramebuffersEXT(1, &data->framebuffers->FBO); |
|
1245 GL_CheckError("", renderer); |
1225 SDL_free(data->framebuffers); |
1246 SDL_free(data->framebuffers); |
1226 data->framebuffers = nextnode; |
1247 data->framebuffers = nextnode; |
1227 } |
1248 } |
1228 /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */ |
1249 /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */ |
1229 SDL_GL_DeleteContext(data->context); |
1250 SDL_GL_DeleteContext(data->context); |