filename | src/pvr2/glutil.c |
changeset | 1282:9f445c5e252b |
prev | 1276:e20a69167093 |
next | 1296:30ecee61f811 |
author | nkeynes |
date | Tue Mar 27 08:23:52 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Android: Preserve render buffers when switching away from app. - fix gl_read_render_buffer + gl_load_frame_buffer to work in GLES a) glReadPixels only (guaranteed to) work for GL_RGBA,GL_UNSIGNED_BYTE b) glTexSubImage2D can only load GL_RGBA into a GL_RGBA render buffer. |
file | annotate | diff | log | raw |
nkeynes@635 | 1 | /** |
nkeynes@636 | 2 | * $Id$ |
nkeynes@635 | 3 | * |
nkeynes@635 | 4 | * GL-based support functions |
nkeynes@635 | 5 | * |
nkeynes@635 | 6 | * Copyright (c) 2005 Nathan Keynes. |
nkeynes@635 | 7 | * |
nkeynes@635 | 8 | * This program is free software; you can redistribute it and/or modify |
nkeynes@635 | 9 | * it under the terms of the GNU General Public License as published by |
nkeynes@635 | 10 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@635 | 11 | * (at your option) any later version. |
nkeynes@635 | 12 | * |
nkeynes@635 | 13 | * This program is distributed in the hope that it will be useful, |
nkeynes@635 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@635 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@635 | 16 | * GNU General Public License for more details. |
nkeynes@635 | 17 | */ |
nkeynes@736 | 18 | |
nkeynes@1282 | 19 | #include <assert.h> |
nkeynes@645 | 20 | #include <string.h> |
nkeynes@1129 | 21 | #include <stdlib.h> |
nkeynes@687 | 22 | #include <glib/gstrfuncs.h> |
nkeynes@635 | 23 | #include "pvr2/glutil.h" |
nkeynes@635 | 24 | |
nkeynes@1258 | 25 | gboolean isOpenGLES2() |
nkeynes@1258 | 26 | { |
nkeynes@1258 | 27 | const char *str = glGetString(GL_VERSION); |
nkeynes@1258 | 28 | if( strncmp(str, "OpenGL ES 2.", 12) == 0 ) { |
nkeynes@1258 | 29 | return TRUE; |
nkeynes@1258 | 30 | } |
nkeynes@1276 | 31 | return FALSE; |
nkeynes@1258 | 32 | } |
nkeynes@1258 | 33 | |
nkeynes@667 | 34 | gboolean isGLSecondaryColorSupported() |
nkeynes@667 | 35 | { |
nkeynes@736 | 36 | return isGLExtensionSupported("GL_EXT_secondary_color"); |
nkeynes@667 | 37 | } |
nkeynes@667 | 38 | |
nkeynes@667 | 39 | gboolean isGLVertexBufferSupported() |
nkeynes@667 | 40 | { |
nkeynes@736 | 41 | return isGLExtensionSupported("GL_ARB_vertex_buffer_object"); |
nkeynes@667 | 42 | } |
nkeynes@667 | 43 | |
nkeynes@667 | 44 | gboolean isGLPixelBufferSupported() |
nkeynes@667 | 45 | { |
nkeynes@736 | 46 | return isGLExtensionSupported("GL_ARB_pixel_buffer_object"); |
nkeynes@667 | 47 | } |
nkeynes@667 | 48 | |
nkeynes@667 | 49 | gboolean isGLMirroredTextureSupported() |
nkeynes@667 | 50 | { |
nkeynes@736 | 51 | return isGLExtensionSupported("GL_ARB_texture_mirrored_repeat"); |
nkeynes@667 | 52 | } |
nkeynes@667 | 53 | |
nkeynes@1275 | 54 | gboolean isGLBGRATextureSupported() |
nkeynes@1275 | 55 | { |
nkeynes@1275 | 56 | /* Note: e.g. Tegra 3 reports GL_EXT_bgra, but it doesn't actually work. |
nkeynes@1275 | 57 | * Need to check this with NVIDIA, in meantime assume GLES2 doesn't have |
nkeynes@1275 | 58 | * BGRA support */ |
nkeynes@1275 | 59 | return !isOpenGLES2() && isGLExtensionSupported("GL_EXT_bgra"); |
nkeynes@1275 | 60 | } |
nkeynes@1275 | 61 | |
nkeynes@1258 | 62 | gboolean isGLShaderSupported() |
nkeynes@1245 | 63 | { |
nkeynes@1258 | 64 | return isOpenGLES2() || (isGLExtensionSupported("GL_ARB_fragment_shader") && |
nkeynes@1258 | 65 | isGLExtensionSupported("GL_ARB_vertex_shader") && |
nkeynes@1258 | 66 | isGLExtensionSupported("GL_ARB_shading_language_100")); |
nkeynes@1245 | 67 | } |
nkeynes@1245 | 68 | |
nkeynes@1140 | 69 | /** |
nkeynes@1140 | 70 | * Check if there's at least 2 texture units |
nkeynes@1140 | 71 | */ |
nkeynes@1140 | 72 | gboolean isGLMultitextureSupported() |
nkeynes@1140 | 73 | { |
nkeynes@1248 | 74 | if( !isOpenGLES2() && !isGLExtensionSupported("GL_ARB_multitexture") ) |
nkeynes@1140 | 75 | return FALSE; |
nkeynes@1140 | 76 | int units = 0; |
nkeynes@1219 | 77 | |
nkeynes@1219 | 78 | #if defined(GL_MAX_TEXTURE_UNITS) |
nkeynes@1219 | 79 | glGetIntegerv(GL_MAX_TEXTURE_UNITS, &units); |
nkeynes@1219 | 80 | #elif defined(GL_MAX_TEXTURE_IMAGE_UNITS) |
nkeynes@1219 | 81 | glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &units); |
nkeynes@1219 | 82 | #endif |
nkeynes@1140 | 83 | return units >= 2; |
nkeynes@1140 | 84 | } |
nkeynes@1140 | 85 | |
nkeynes@1134 | 86 | gboolean isGLVertexRangeSupported() |
nkeynes@1134 | 87 | { |
nkeynes@1134 | 88 | return isGLExtensionSupported("GL_APPLE_vertex_array_range") || |
nkeynes@1134 | 89 | isGLExtensionSupported("GL_NV_vertex_array_range"); |
nkeynes@1134 | 90 | } |
nkeynes@1134 | 91 | |
nkeynes@635 | 92 | /** |
nkeynes@635 | 93 | * Test if a specific extension is supported. From opengl.org |
nkeynes@635 | 94 | * @param extension extension name to check for |
nkeynes@635 | 95 | * @return TRUE if supported, otherwise FALSE. |
nkeynes@635 | 96 | */ |
nkeynes@635 | 97 | gboolean isGLExtensionSupported( const char *extension ) |
nkeynes@635 | 98 | { |
nkeynes@635 | 99 | const GLubyte *extensions = NULL; |
nkeynes@635 | 100 | const GLubyte *start; |
nkeynes@635 | 101 | GLubyte *where, *terminator; |
nkeynes@635 | 102 | |
nkeynes@635 | 103 | /* Extension names should not have spaces. */ |
nkeynes@635 | 104 | where = (GLubyte *) strchr(extension, ' '); |
nkeynes@635 | 105 | if (where || *extension == '\0') |
nkeynes@736 | 106 | return 0; |
nkeynes@635 | 107 | extensions = glGetString(GL_EXTENSIONS); |
nkeynes@645 | 108 | if( extensions == NULL ) { |
nkeynes@736 | 109 | /* No GL available, so we're pretty sure the extension isn't |
nkeynes@736 | 110 | * available either. */ |
nkeynes@736 | 111 | return FALSE; |
nkeynes@645 | 112 | } |
nkeynes@635 | 113 | /* It takes a bit of care to be fool-proof about parsing the |
nkeynes@635 | 114 | OpenGL extensions string. Don't be fooled by sub-strings, |
nkeynes@635 | 115 | etc. */ |
nkeynes@635 | 116 | start = extensions; |
nkeynes@635 | 117 | for (;;) { |
nkeynes@736 | 118 | where = (GLubyte *) strstr((const char *) start, extension); |
nkeynes@736 | 119 | if (!where) |
nkeynes@736 | 120 | break; |
nkeynes@736 | 121 | terminator = where + strlen(extension); |
nkeynes@736 | 122 | if (where == start || *(where - 1) == ' ') |
nkeynes@736 | 123 | if (*terminator == ' ' || *terminator == '\0') |
nkeynes@736 | 124 | return TRUE; |
nkeynes@736 | 125 | start = terminator; |
nkeynes@635 | 126 | } |
nkeynes@635 | 127 | return FALSE; |
nkeynes@635 | 128 | } |
nkeynes@687 | 129 | |
nkeynes@1129 | 130 | int compare_charp( const void *a, const void *b ) |
nkeynes@1129 | 131 | { |
nkeynes@1129 | 132 | const char **ca = (const char **)a; |
nkeynes@1129 | 133 | const char **cb = (const char **)b; |
nkeynes@1129 | 134 | return strcmp(*ca, *cb); |
nkeynes@1129 | 135 | } |
nkeynes@1129 | 136 | |
nkeynes@1134 | 137 | #define DEFAULT_TERMINAL_COLUMNS 80 |
nkeynes@1134 | 138 | #define DEFAULT_COLUMN_WIDTH 34 |
nkeynes@1134 | 139 | |
nkeynes@1223 | 140 | int glGetMaxColourAttachments() |
nkeynes@1223 | 141 | { |
nkeynes@1223 | 142 | #ifdef GL_MAX_COLOR_ATTACHMENTS |
nkeynes@1223 | 143 | GLint result = 0; |
nkeynes@1223 | 144 | glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &result); |
nkeynes@1223 | 145 | return result; |
nkeynes@1223 | 146 | #else |
nkeynes@1223 | 147 | return 1; |
nkeynes@1223 | 148 | #endif |
nkeynes@1223 | 149 | } |
nkeynes@1223 | 150 | |
nkeynes@1223 | 151 | |
nkeynes@1134 | 152 | /** |
nkeynes@1236 | 153 | * Define an orthographic projection matrix |
nkeynes@1236 | 154 | * Note: row-major order |
nkeynes@1236 | 155 | */ |
nkeynes@1236 | 156 | void defineOrthoMatrix( GLfloat *matrix, GLfloat width, GLfloat height, GLfloat znear, GLfloat zfar ) |
nkeynes@1236 | 157 | { |
nkeynes@1236 | 158 | matrix[0] = 2/width; |
nkeynes@1236 | 159 | matrix[1] = 0; |
nkeynes@1236 | 160 | matrix[2] = 0; |
nkeynes@1236 | 161 | matrix[3] = 0; |
nkeynes@1236 | 162 | |
nkeynes@1236 | 163 | matrix[4] = 0; |
nkeynes@1236 | 164 | matrix[5] = -2/height; |
nkeynes@1236 | 165 | matrix[6] = 0; |
nkeynes@1236 | 166 | matrix[7] = 0; |
nkeynes@1236 | 167 | |
nkeynes@1236 | 168 | matrix[8] = 0; |
nkeynes@1236 | 169 | matrix[9] = 0; |
nkeynes@1236 | 170 | matrix[10]= -2/(zfar-znear); |
nkeynes@1236 | 171 | matrix[11]= 0; |
nkeynes@1236 | 172 | |
nkeynes@1236 | 173 | matrix[12]= -1; |
nkeynes@1236 | 174 | matrix[13]= 1; |
nkeynes@1236 | 175 | matrix[14]= -(zfar+znear)/(zfar-znear); |
nkeynes@1236 | 176 | matrix[15]= 1; |
nkeynes@1236 | 177 | } |
nkeynes@1236 | 178 | |
nkeynes@1236 | 179 | /** |
nkeynes@1134 | 180 | * Format a GL extension list (or other space-separated string) nicely, and |
nkeynes@1134 | 181 | * print to the given output stream. |
nkeynes@1134 | 182 | */ |
nkeynes@1134 | 183 | |
nkeynes@1134 | 184 | void fprint_extensions( FILE *out, const char *extensions ) |
nkeynes@687 | 185 | { |
nkeynes@1134 | 186 | unsigned int i, j, count, maxlen = DEFAULT_COLUMN_WIDTH, columns, per_column, terminal_columns; |
nkeynes@1134 | 187 | const char *terminal_columns_str = getenv("COLUMNS"); |
nkeynes@1134 | 188 | if( terminal_columns_str == NULL || (terminal_columns = strtol(terminal_columns_str,0,10)) == 0 ) |
nkeynes@1134 | 189 | terminal_columns = DEFAULT_TERMINAL_COLUMNS; |
nkeynes@1129 | 190 | |
nkeynes@1134 | 191 | if( extensions == NULL || extensions[0] == '\0' ) |
nkeynes@1134 | 192 | return; |
nkeynes@1134 | 193 | |
nkeynes@1134 | 194 | gchar *ext_dup = g_strdup(extensions); |
nkeynes@1134 | 195 | gchar **ext_split = g_strsplit(g_strstrip(extensions), " ", 0); |
nkeynes@1134 | 196 | for( count = 0; ext_split[count] != NULL; count++ ) { |
nkeynes@1134 | 197 | unsigned len = strlen(ext_split[count]); |
nkeynes@1134 | 198 | if( len > maxlen ) |
nkeynes@1134 | 199 | maxlen = len; |
nkeynes@1134 | 200 | } |
nkeynes@1134 | 201 | |
nkeynes@1134 | 202 | columns = terminal_columns / (maxlen+2); |
nkeynes@1134 | 203 | if( columns == 0 ) |
nkeynes@1134 | 204 | columns = 1; |
nkeynes@1134 | 205 | per_column = (count+columns-1) / columns; |
nkeynes@1129 | 206 | |
nkeynes@1129 | 207 | qsort(ext_split, count, sizeof(gchar *), compare_charp); |
nkeynes@736 | 208 | |
nkeynes@1134 | 209 | for( i=0; i<per_column; i++ ) { |
nkeynes@1134 | 210 | for( j=0; j<columns; j++ ) { |
nkeynes@1134 | 211 | unsigned idx = i + (j*per_column); |
nkeynes@1134 | 212 | if( idx < count ) |
nkeynes@1134 | 213 | fprintf( out, " %-*s", maxlen, ext_split[idx] ); |
nkeynes@1134 | 214 | } |
nkeynes@1134 | 215 | fprintf( out, "\n" ); |
nkeynes@1134 | 216 | } |
nkeynes@1134 | 217 | g_strfreev(ext_split); |
nkeynes@1134 | 218 | g_free(ext_dup); |
nkeynes@1134 | 219 | } |
nkeynes@1134 | 220 | |
nkeynes@1134 | 221 | void glPrintInfo( FILE *out ) |
nkeynes@1134 | 222 | { |
nkeynes@687 | 223 | fprintf( out, "GL Vendor: %s\n", glGetString(GL_VENDOR) ); |
nkeynes@687 | 224 | fprintf( out, "GL Renderer: %s\n", glGetString(GL_RENDERER) ); |
nkeynes@687 | 225 | fprintf( out, "GL Version: %s\n", glGetString(GL_VERSION) ); |
nkeynes@1258 | 226 | if( isGLShaderSupported() ) { |
nkeynes@1258 | 227 | fprintf( out, "SL Version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION) ); |
nkeynes@1134 | 228 | } |
nkeynes@736 | 229 | |
nkeynes@1134 | 230 | fprintf( out, "GL Extensions:\n" ); |
nkeynes@1134 | 231 | |
nkeynes@1134 | 232 | fprint_extensions( out, (const gchar *)glGetString(GL_EXTENSIONS) ); |
nkeynes@1134 | 233 | if( display_driver && display_driver->print_info ) { |
nkeynes@1134 | 234 | fprintf( out, "\n"); |
nkeynes@1134 | 235 | display_driver->print_info(out); |
nkeynes@687 | 236 | } |
nkeynes@687 | 237 | } |
nkeynes@1150 | 238 | |
nkeynes@1150 | 239 | gboolean gl_check_error(const char *context) |
nkeynes@1150 | 240 | { |
nkeynes@1150 | 241 | GLint err = glGetError(); |
nkeynes@1150 | 242 | if( err != 0 ) { |
nkeynes@1150 | 243 | const char *s; |
nkeynes@1150 | 244 | switch( err ) { |
nkeynes@1150 | 245 | case GL_INVALID_ENUM: s = "Invalid enum"; break; |
nkeynes@1150 | 246 | case GL_INVALID_VALUE: s = "Invalid value"; break; |
nkeynes@1150 | 247 | case GL_INVALID_OPERATION: s = "Invalid operation"; break; |
nkeynes@1219 | 248 | #ifdef GL_STACK_OVERFLOW |
nkeynes@1150 | 249 | case GL_STACK_OVERFLOW: s = "Stack overflow"; break; |
nkeynes@1220 | 250 | #endif |
nkeynes@1220 | 251 | #ifdef GL_STACK_UNDERFLOW |
nkeynes@1150 | 252 | case GL_STACK_UNDERFLOW: s = "Stack underflow"; break; |
nkeynes@1220 | 253 | #endif |
nkeynes@1150 | 254 | case GL_OUT_OF_MEMORY: s = "Out of memory"; break; |
nkeynes@1150 | 255 | default: s = "Unknown error"; break; |
nkeynes@1150 | 256 | } |
nkeynes@1150 | 257 | if( context ) { |
nkeynes@1282 | 258 | WARN( "%s: GL error: %x (%s)", context, err, s ); |
nkeynes@1150 | 259 | } else { |
nkeynes@1282 | 260 | WARN( "GL error: %x (%s)", err, s ); |
nkeynes@1150 | 261 | } |
nkeynes@1159 | 262 | return FALSE; |
nkeynes@1150 | 263 | } |
nkeynes@1159 | 264 | return TRUE; |
nkeynes@1150 | 265 | } |
nkeynes@1282 | 266 | |
nkeynes@1282 | 267 | static int bgra_to_rgba_type( int glFormatType ) |
nkeynes@1282 | 268 | { |
nkeynes@1282 | 269 | switch( glFormatType ) { |
nkeynes@1282 | 270 | case GL_UNSIGNED_SHORT_1_5_5_5_REV: |
nkeynes@1282 | 271 | return GL_UNSIGNED_SHORT_5_5_5_1; |
nkeynes@1282 | 272 | case GL_UNSIGNED_SHORT_4_4_4_4_REV: |
nkeynes@1282 | 273 | return GL_UNSIGNED_SHORT_4_4_4_4; |
nkeynes@1282 | 274 | case GL_UNSIGNED_BYTE: |
nkeynes@1282 | 275 | return GL_UNSIGNED_BYTE; |
nkeynes@1282 | 276 | default: |
nkeynes@1282 | 277 | assert( 0 && "Unsupported BGRA format" ); |
nkeynes@1282 | 278 | return glFormatType; |
nkeynes@1282 | 279 | } |
nkeynes@1282 | 280 | } |
nkeynes@1282 | 281 | |
nkeynes@1282 | 282 | /** |
nkeynes@1282 | 283 | * Convert BGRA data in buffer to RGBA format in-place (for systems that don't natively |
nkeynes@1282 | 284 | * support BGRA). |
nkeynes@1282 | 285 | * @return converted format type |
nkeynes@1282 | 286 | * @param data BGRA pixel data |
nkeynes@1282 | 287 | * @param nPixels total number of pixels (width*height) |
nkeynes@1282 | 288 | * @param glFormatType GL format of source data. One of |
nkeynes@1282 | 289 | * GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_SHORT_4_4_4_4_REV, or GL_UNSIGNED_BYTE |
nkeynes@1282 | 290 | */ |
nkeynes@1282 | 291 | static int bgra_to_rgba( unsigned char *data, unsigned nPixels, int glFormatType ) |
nkeynes@1282 | 292 | { |
nkeynes@1282 | 293 | unsigned i; |
nkeynes@1282 | 294 | switch( glFormatType ) { |
nkeynes@1282 | 295 | case GL_UNSIGNED_SHORT_1_5_5_5_REV: { |
nkeynes@1282 | 296 | uint16_t *p = (uint16_t *)data; |
nkeynes@1282 | 297 | uint16_t *end = p + nPixels; |
nkeynes@1282 | 298 | while( p != end ) { |
nkeynes@1282 | 299 | uint16_t v = *p; |
nkeynes@1282 | 300 | *p = (v >> 15) | (v<<1); |
nkeynes@1282 | 301 | p++; |
nkeynes@1282 | 302 | } |
nkeynes@1282 | 303 | return GL_UNSIGNED_SHORT_5_5_5_1; |
nkeynes@1282 | 304 | } |
nkeynes@1282 | 305 | case GL_UNSIGNED_SHORT_4_4_4_4_REV: { /* ARGB => RGBA */ |
nkeynes@1282 | 306 | uint16_t *p = (uint16_t *)data; |
nkeynes@1282 | 307 | uint16_t *end = p + nPixels; |
nkeynes@1282 | 308 | while( p != end ) { |
nkeynes@1282 | 309 | uint16_t v = *p; |
nkeynes@1282 | 310 | *p = (v >> 12) | (v<<4); |
nkeynes@1282 | 311 | p++; |
nkeynes@1282 | 312 | } |
nkeynes@1282 | 313 | return GL_UNSIGNED_SHORT_4_4_4_4; |
nkeynes@1282 | 314 | } |
nkeynes@1282 | 315 | case GL_UNSIGNED_BYTE: { /* ARGB => ABGR */ |
nkeynes@1282 | 316 | uint32_t *p = (uint32_t *)data; |
nkeynes@1282 | 317 | uint32_t *end = p + nPixels; |
nkeynes@1282 | 318 | while( p != end ) { |
nkeynes@1282 | 319 | uint32_t v = *p; |
nkeynes@1282 | 320 | *p = (v&0xFF000000) | ((v<<16) & 0x00FF0000) | (v & 0x0000FF00) | ((v>>16) & 0x000000FF); |
nkeynes@1282 | 321 | p++; |
nkeynes@1282 | 322 | } |
nkeynes@1282 | 323 | return GL_UNSIGNED_BYTE; |
nkeynes@1282 | 324 | } |
nkeynes@1282 | 325 | default: |
nkeynes@1282 | 326 | assert( 0 && "Unsupported BGRA format" ); |
nkeynes@1282 | 327 | return glFormatType; |
nkeynes@1282 | 328 | } |
nkeynes@1282 | 329 | } |
nkeynes@1282 | 330 | |
nkeynes@1282 | 331 | void glTexImage2DBGRA( int level, GLint intFormat, int width, int height, GLint format, GLint type, unsigned char *data, int preserveData ) |
nkeynes@1282 | 332 | { |
nkeynes@1282 | 333 | if( format == GL_BGRA && !display_driver->capabilities.has_bgra ) { |
nkeynes@1282 | 334 | if( preserveData ) { |
nkeynes@1282 | 335 | size_t size = width * height * (type == GL_UNSIGNED_BYTE ? 4 : 2); |
nkeynes@1282 | 336 | char buf[size]; |
nkeynes@1282 | 337 | memcpy(buf, data, size); |
nkeynes@1282 | 338 | GLint rgbaType = bgra_to_rgba( buf, width*height, type ); |
nkeynes@1282 | 339 | glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, GL_RGBA, rgbaType, |
nkeynes@1282 | 340 | buf ); |
nkeynes@1282 | 341 | } else { |
nkeynes@1282 | 342 | GLint rgbaType = bgra_to_rgba( data, width*height, type ); |
nkeynes@1282 | 343 | glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, GL_RGBA, rgbaType, |
nkeynes@1282 | 344 | data ); |
nkeynes@1282 | 345 | } |
nkeynes@1282 | 346 | } else { |
nkeynes@1282 | 347 | glTexImage2D( GL_TEXTURE_2D, level, intFormat, width, height, 0, format, type, |
nkeynes@1282 | 348 | data ); |
nkeynes@1282 | 349 | } |
nkeynes@1282 | 350 | } |
nkeynes@1282 | 351 | |
nkeynes@1282 | 352 | void glTexSubImage2DBGRA( int level, int xoff, int yoff, int width, int height, GLint format, GLint type, unsigned char *data, int preserveData ) |
nkeynes@1282 | 353 | { |
nkeynes@1282 | 354 | if( format == GL_BGRA && !display_driver->capabilities.has_bgra ) { |
nkeynes@1282 | 355 | if( preserveData ) { |
nkeynes@1282 | 356 | size_t size = width * height * (type == GL_UNSIGNED_BYTE ? 4 : 2); |
nkeynes@1282 | 357 | char buf[size]; |
nkeynes@1282 | 358 | memcpy(buf, data, size); |
nkeynes@1282 | 359 | GLint rgbaType = bgra_to_rgba( buf, width*height, type ); |
nkeynes@1282 | 360 | glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, GL_RGBA, rgbaType, |
nkeynes@1282 | 361 | buf ); |
nkeynes@1282 | 362 | } else { |
nkeynes@1282 | 363 | GLint rgbaType = bgra_to_rgba( data, width*height, type ); |
nkeynes@1282 | 364 | glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, GL_RGBA, rgbaType, |
nkeynes@1282 | 365 | data ); |
nkeynes@1282 | 366 | } |
nkeynes@1282 | 367 | } else { |
nkeynes@1282 | 368 | glTexSubImage2D( GL_TEXTURE_2D, level, xoff, yoff, width, height, format, type, |
nkeynes@1282 | 369 | data ); |
nkeynes@1282 | 370 | } |
nkeynes@1282 | 371 | } |
.