David Li | aa1f54d | 2011-03-01 16:54:04 -0800 | [diff] [blame^] | 1 | #include "gles2context.h" |
| 2 | |
| 3 | //#undef LOGD |
| 4 | //#define LOGD(...) |
| 5 | |
| 6 | #define API_ENTRY |
| 7 | #define CALL_GL_API(NAME,...) LOGD("?"#NAME); assert(0); |
| 8 | #define CALL_GL_API_RETURN(NAME,...) LOGD("?"#NAME); assert(0); return 0; |
| 9 | |
| 10 | static inline GGLTexture * AllocTexture() |
| 11 | { |
| 12 | GGLTexture * tex = (GGLTexture *)calloc(1, sizeof(GGLTexture)); |
| 13 | tex->minFilter = GGLTexture::GGL_LINEAR; // should be NEAREST_ MIPMAP_LINEAR |
| 14 | tex->magFilter = GGLTexture::GGL_LINEAR; |
| 15 | return tex; |
| 16 | } |
| 17 | |
| 18 | void GLES2Context::InitializeTextures() |
| 19 | { |
| 20 | tex.textures = std::map<GLuint, GGLTexture *>(); // the entire struct has been zeroed in constructor |
| 21 | tex.tex2D = AllocTexture(); |
| 22 | tex.textures[GL_TEXTURE_2D] = tex.tex2D; |
| 23 | tex.texCube = AllocTexture(); |
| 24 | tex.textures[GL_TEXTURE_CUBE_MAP] = tex.texCube; |
| 25 | for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) { |
| 26 | tex.tmus[i] = NULL; |
| 27 | tex.sampler2tmu[i] = NULL; |
| 28 | } |
| 29 | |
| 30 | tex.active = 0; |
| 31 | |
| 32 | tex.free = max(GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP) + 1; |
| 33 | |
| 34 | tex.tex2D->format = GGL_PIXEL_FORMAT_RGBA_8888; |
| 35 | tex.tex2D->type = GL_TEXTURE_2D; |
| 36 | tex.tex2D->levelCount = 1; |
| 37 | tex.tex2D->wrapS = tex.tex2D->wrapT = GGLTexture::GGL_REPEAT; |
| 38 | tex.tex2D->minFilter = tex.tex2D->magFilter = GGLTexture::GGL_NEAREST; |
| 39 | tex.tex2D->width = tex.tex2D->height = 1; |
| 40 | tex.tex2D->levels = malloc(4); |
| 41 | *(unsigned *)tex.tex2D->levels = 0xff000000; |
| 42 | |
| 43 | |
| 44 | tex.texCube->format = GGL_PIXEL_FORMAT_RGBA_8888; |
| 45 | tex.texCube->type = GL_TEXTURE_CUBE_MAP; |
| 46 | tex.texCube->levelCount = 1; |
| 47 | tex.texCube->wrapS = tex.texCube->wrapT = GGLTexture::GGL_REPEAT; |
| 48 | tex.texCube->minFilter = tex.texCube->magFilter = GGLTexture::GGL_NEAREST; |
| 49 | tex.texCube->width = tex.texCube->height = 1; |
| 50 | tex.texCube->levels = malloc(4 * 6); |
| 51 | static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000, |
| 52 | 0xff00ffff, 0xffffff00, 0xffff00ff |
| 53 | }; |
| 54 | memcpy(tex.texCube->levels, texels, sizeof texels); |
| 55 | |
| 56 | //texture.levelCount = GenerateMipmaps(texture.levels, texture.width, texture.height); |
| 57 | |
| 58 | // static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000, |
| 59 | // 0xff00ffff, 0xffffff00, 0xffff00ff}; |
| 60 | // memcpy(texture.levels[0], texels, sizeof texels); |
| 61 | // texture.format = GGL_PIXEL_FORMAT_RGBA_8888; |
| 62 | // texture.width = texture.height = 1; |
| 63 | //texture.height /= 6; |
| 64 | //texture.type = GL_TEXTURE_CUBE_MAP; |
| 65 | |
| 66 | tex.unpack = 4; |
| 67 | } |
| 68 | |
| 69 | void GLES2Context::TextureState::UpdateSampler(GGLInterface * iface, unsigned tmu) |
| 70 | { |
| 71 | for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) |
| 72 | if (tmu == sampler2tmu[i]) |
| 73 | iface->SetSampler(iface, i, tmus[tmu]); |
| 74 | } |
| 75 | |
| 76 | void GLES2Context::UninitializeTextures() |
| 77 | { |
| 78 | for (std::map<GLuint, GGLTexture *>::iterator it = tex.textures.begin(); it != tex.textures.end(); it++) { |
| 79 | if (!it->second) |
| 80 | continue; |
| 81 | free(it->second->levels); |
| 82 | free(it->second); |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | static inline void GetFormatAndBytesPerPixel(const GLenum format, unsigned * bytesPerPixel, |
| 87 | GGLPixelFormat * texFormat) |
| 88 | { |
| 89 | switch (format) { |
| 90 | case GL_ALPHA: |
| 91 | *texFormat = GGL_PIXEL_FORMAT_A_8; |
| 92 | *bytesPerPixel = 1; |
| 93 | break; |
| 94 | case GL_LUMINANCE: |
| 95 | *texFormat = GGL_PIXEL_FORMAT_L_8; |
| 96 | *bytesPerPixel = 1; |
| 97 | break; |
| 98 | case GL_LUMINANCE_ALPHA: |
| 99 | *texFormat = GGL_PIXEL_FORMAT_LA_88; |
| 100 | *bytesPerPixel = 2; |
| 101 | break; |
| 102 | case GL_RGB: |
| 103 | *texFormat = GGL_PIXEL_FORMAT_RGB_888; |
| 104 | *bytesPerPixel = 3; |
| 105 | break; |
| 106 | case GL_RGBA: |
| 107 | *texFormat = GGL_PIXEL_FORMAT_RGBA_8888; |
| 108 | *bytesPerPixel = 4; |
| 109 | break; |
| 110 | |
| 111 | // internal formats to avoid conversion |
| 112 | case GL_UNSIGNED_SHORT_5_6_5: |
| 113 | *texFormat = GGL_PIXEL_FORMAT_RGB_565; |
| 114 | *bytesPerPixel = 2; |
| 115 | break; |
| 116 | |
| 117 | default: |
| 118 | assert(0); |
| 119 | return; |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | static inline void CopyTexture(char * dst, const char * src, const unsigned bytesPerPixel, |
| 124 | const unsigned sx, const unsigned sy, const unsigned sw, |
| 125 | const unsigned dx, const unsigned dy, const unsigned dw, |
| 126 | const unsigned w, const unsigned h) |
| 127 | { |
| 128 | const unsigned bpp = bytesPerPixel; |
| 129 | if (dw == sw && dw == w && sx == 0 && dx == 0) |
| 130 | memcpy(dst + dy * dw * bpp, src + sy * sw * bpp, w * h * bpp); |
| 131 | else |
| 132 | for (unsigned y = 0; y < h; y++) |
| 133 | memcpy(dst + ((dy + y) * dw + dx) * bpp, src + ((sy + y) * sw + sx) * bpp, w * bpp); |
| 134 | } |
| 135 | |
| 136 | void glActiveTexture(GLenum texture) |
| 137 | { |
| 138 | GLES2_GET_CONST_CONTEXT(ctx); |
| 139 | unsigned index = texture - GL_TEXTURE0; |
| 140 | assert(NELEM(ctx->tex.tmus) > index); |
| 141 | // LOGD("agl2: glActiveTexture %u", index); |
| 142 | ctx->tex.active = index; |
| 143 | } |
| 144 | |
| 145 | void glBindTexture(GLenum target, GLuint texture) |
| 146 | { |
| 147 | GLES2_GET_CONST_CONTEXT(ctx); |
| 148 | // LOGD("agl2: glBindTexture target=0x%.4X texture=%u active=%u", target, texture, ctx->tex.active); |
| 149 | std::map<GLuint, GGLTexture *>::iterator it = ctx->tex.textures.find(texture); |
| 150 | GGLTexture * tex = NULL; |
| 151 | if (it != ctx->tex.textures.end()) { |
| 152 | tex = it->second; |
| 153 | if (!tex) { |
| 154 | tex = AllocTexture(); |
| 155 | tex->type = target; |
| 156 | it->second = tex; |
| 157 | // LOGD("agl2: glBindTexture allocTexture"); |
| 158 | } |
| 159 | // else |
| 160 | // LOGD("agl2: glBindTexture bind existing texture"); |
| 161 | assert(target == tex->type); |
| 162 | } else if (0 == texture) { |
| 163 | if (GL_TEXTURE_2D == target) |
| 164 | { |
| 165 | tex = ctx->tex.tex2D; |
| 166 | // LOGD("agl2: glBindTexture bind default tex2D"); |
| 167 | } |
| 168 | else if (GL_TEXTURE_CUBE_MAP == target) |
| 169 | { |
| 170 | tex = ctx->tex.texCube; |
| 171 | // LOGD("agl2: glBindTexture bind default texCube"); |
| 172 | } |
| 173 | else |
| 174 | assert(0); |
| 175 | } else { |
| 176 | if (texture <= ctx->tex.free) |
| 177 | ctx->tex.free = texture + 1; |
| 178 | tex = AllocTexture(); |
| 179 | tex->type = target; |
| 180 | ctx->tex.textures[texture] = tex; |
| 181 | // LOGD("agl2: glBindTexture new texture=%u", texture); |
| 182 | } |
| 183 | ctx->tex.tmus[ctx->tex.active] = tex; |
| 184 | // LOGD("agl2: glBindTexture format=0x%.2X w=%u h=%u levels=%p", tex->format, |
| 185 | // tex->width, tex->height, tex->levels); |
| 186 | ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); |
| 187 | } |
| 188 | |
| 189 | void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) |
| 190 | { |
| 191 | CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data); |
| 192 | } |
| 193 | |
| 194 | void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) |
| 195 | { |
| 196 | CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data); |
| 197 | } |
| 198 | |
| 199 | void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, |
| 200 | GLint x, GLint y, GLsizei width, GLsizei height, GLint border) |
| 201 | { |
| 202 | GLES2_GET_CONST_CONTEXT(ctx); |
| 203 | // LOGD("agl2: glCopyTexImage2D target=0x%.4X internalformat=0x%.4X", target, internalformat); |
| 204 | // LOGD("x=%d y=%d width=%d height=%d border=%d level=%d ", x, y, width, height, border, level); |
| 205 | assert(0 == border); |
| 206 | assert(0 == level); |
| 207 | unsigned bytesPerPixel = 0; |
| 208 | GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN; |
| 209 | GetFormatAndBytesPerPixel(internalformat, &bytesPerPixel, &texFormat); |
| 210 | |
| 211 | assert(texFormat == ctx->rasterizer.frameSurface.format); |
| 212 | // LOGD("texFormat=0x%.2X bytesPerPixel=%d \n", texFormat, bytesPerPixel); |
| 213 | unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size; |
| 214 | |
| 215 | assert(ctx->tex.tmus[ctx->tex.active]); |
| 216 | assert(y + height <= ctx->rasterizer.frameSurface.height); |
| 217 | assert(x + width <= ctx->rasterizer.frameSurface.width); |
| 218 | GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active]; |
| 219 | tex.width = width; |
| 220 | tex.height = height; |
| 221 | tex.levelCount = 1; |
| 222 | tex.format = texFormat; |
| 223 | switch (target) { |
| 224 | case GL_TEXTURE_2D: |
| 225 | tex.levels = realloc(tex.levels, totalSize); |
| 226 | CopyTexture((char *)tex.levels, (const char *)ctx->rasterizer.frameSurface.data, bytesPerPixel, |
| 227 | x, y, ctx->rasterizer.frameSurface.width, 0, 0, width, width, height); |
| 228 | break; |
| 229 | default: |
| 230 | assert(0); |
| 231 | return; |
| 232 | } |
| 233 | ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); |
| 234 | } |
| 235 | |
| 236 | void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) |
| 237 | { |
| 238 | // x, y are src offset |
| 239 | // xoffset and yoffset are dst offset |
| 240 | GLES2_GET_CONST_CONTEXT(ctx); |
| 241 | // LOGD("agl2: glCopyTexSubImage2D target=0x%.4X level=%d", target, level); |
| 242 | // LOGD("xoffset=%d yoffset=%d x=%d y=%d width=%d height=%d", xoffset, yoffset, x, y, width, height); |
| 243 | assert(0 == level); |
| 244 | |
| 245 | unsigned bytesPerPixel = 4; |
| 246 | unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size; |
| 247 | |
| 248 | assert(ctx->tex.tmus[ctx->tex.active]); |
| 249 | GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active]; |
| 250 | |
| 251 | assert(tex.format == ctx->rasterizer.frameSurface.format); |
| 252 | assert(GGL_PIXEL_FORMAT_RGBA_8888 == tex.format); |
| 253 | |
| 254 | const unsigned srcWidth = ctx->rasterizer.frameSurface.width; |
| 255 | const unsigned srcHeight = ctx->rasterizer.frameSurface.height; |
| 256 | |
| 257 | assert(x >= 0 && y >= 0); |
| 258 | assert(xoffset >= 0 && yoffset >= 0); |
| 259 | assert(x + width <= srcWidth); |
| 260 | assert(y + height <= srcHeight); |
| 261 | assert(xoffset + width <= tex.width); |
| 262 | assert(yoffset + height <= tex.height); |
| 263 | |
| 264 | switch (target) { |
| 265 | case GL_TEXTURE_2D: |
| 266 | CopyTexture((char *)tex.levels, (const char *)ctx->rasterizer.frameSurface.data, bytesPerPixel, |
| 267 | x, y, srcWidth, xoffset, yoffset, tex.width, width, height); |
| 268 | break; |
| 269 | default: |
| 270 | assert(0); |
| 271 | return; |
| 272 | } |
| 273 | ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); |
| 274 | } |
| 275 | |
| 276 | void glDeleteTextures(GLsizei n, const GLuint* textures) |
| 277 | { |
| 278 | GLES2_GET_CONST_CONTEXT(ctx); |
| 279 | for (unsigned i = 0; i < n; i++) { |
| 280 | std::map<GLuint, GGLTexture *>::iterator it = ctx->tex.textures.find(textures[i]); |
| 281 | if (it == ctx->tex.textures.end()) |
| 282 | continue; |
| 283 | ctx->tex.free = min(ctx->tex.free, textures[i]); |
| 284 | for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) |
| 285 | if (ctx->tex.tmus[i] == it->second) { |
| 286 | if (GL_TEXTURE_2D == it->second->type) |
| 287 | ctx->tex.tmus[i] = ctx->tex.tex2D; |
| 288 | else if (GL_TEXTURE_CUBE_MAP == it->second->type) |
| 289 | ctx->tex.tmus[i] = ctx->tex.texCube; |
| 290 | else |
| 291 | assert(0); |
| 292 | ctx->tex.UpdateSampler(ctx->iface, i); |
| 293 | } |
| 294 | if (it->second) { |
| 295 | free(it->second->levels); |
| 296 | free(it->second); |
| 297 | } |
| 298 | ctx->tex.textures.erase(it); |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | void glGenTextures(GLsizei n, GLuint* textures) |
| 303 | { |
| 304 | GLES2_GET_CONST_CONTEXT(ctx); |
| 305 | for (unsigned i = 0; i < n; i++) { |
| 306 | textures[i] = 0; |
| 307 | for (ctx->tex.free; ctx->tex.free < 0xffffffffu; ctx->tex.free++) |
| 308 | if (ctx->tex.textures.find(ctx->tex.free) == ctx->tex.textures.end()) { |
| 309 | ctx->tex.textures[ctx->tex.free] = NULL; |
| 310 | textures[i] = ctx->tex.free; |
| 311 | ctx->tex.free++; |
| 312 | break; |
| 313 | } |
| 314 | assert(textures[i]); |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) |
| 319 | { |
| 320 | CALL_GL_API(glGetTexParameterfv, target, pname, params); |
| 321 | } |
| 322 | void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params) |
| 323 | { |
| 324 | CALL_GL_API(glGetTexParameteriv, target, pname, params); |
| 325 | } |
| 326 | |
| 327 | GLboolean glIsTexture(GLuint texture) |
| 328 | { |
| 329 | GLES2_GET_CONST_CONTEXT(ctx); |
| 330 | if (ctx->tex.textures.find(texture) == ctx->tex.textures.end()) |
| 331 | return GL_FALSE; |
| 332 | else |
| 333 | return GL_TRUE; |
| 334 | } |
| 335 | |
| 336 | void glPixelStorei(GLenum pname, GLint param) |
| 337 | { |
| 338 | GLES2_GET_CONST_CONTEXT(ctx); |
| 339 | assert(GL_UNPACK_ALIGNMENT == pname); |
| 340 | assert(1 == param || 2 == param || 4 == param || 8 == param); |
| 341 | // LOGD("\n*\n* agl2: glPixelStorei not implemented pname=0x%.4X param=%d \n*", pname, param); |
| 342 | ctx->tex.unpack = param; |
| 343 | // CALL_GL_API(glPixelStorei, pname, param); |
| 344 | } |
| 345 | void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, |
| 346 | GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) |
| 347 | { |
| 348 | GLES2_GET_CONST_CONTEXT(ctx); |
| 349 | // LOGD("agl2: glTexImage2D internalformat=0x%.4X format=0x%.4X type=0x%.4X \n", internalformat, format, type); |
| 350 | // LOGD("width=%d height=%d border=%d level=%d pixels=%p \n", width, height, border, level, pixels); |
| 351 | switch (type) { |
| 352 | case GL_UNSIGNED_BYTE: |
| 353 | break; |
| 354 | case GL_UNSIGNED_SHORT_5_6_5: |
| 355 | internalformat = format = GL_UNSIGNED_SHORT_5_6_5; |
| 356 | assert(4 == ctx->tex.unpack); |
| 357 | break; |
| 358 | default: |
| 359 | assert(0); |
| 360 | } |
| 361 | assert(internalformat == format); |
| 362 | assert(0 == border); |
| 363 | if (0 != level) { |
| 364 | LOGD("agl2: glTexImage2D level=%d", level); |
| 365 | return; |
| 366 | } |
| 367 | unsigned bytesPerPixel = 0; |
| 368 | GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN; |
| 369 | GetFormatAndBytesPerPixel(format, &bytesPerPixel, &texFormat); |
| 370 | |
| 371 | assert(texFormat && bytesPerPixel); |
| 372 | // LOGD("texFormat=0x%.2X bytesPerPixel=%d active=%u", texFormat, bytesPerPixel, ctx->tex.active); |
| 373 | unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size; |
| 374 | |
| 375 | assert(ctx->tex.tmus[ctx->tex.active]); |
| 376 | |
| 377 | GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active]; |
| 378 | tex.width = width; |
| 379 | tex.height = height; |
| 380 | tex.levelCount = 1; |
| 381 | tex.format = texFormat; |
| 382 | |
| 383 | switch (target) { |
| 384 | case GL_TEXTURE_2D: |
| 385 | assert(GL_TEXTURE_2D == ctx->tex.tmus[ctx->tex.active]->type); |
| 386 | offset = 0; |
| 387 | break; |
| 388 | break; |
| 389 | case GL_TEXTURE_CUBE_MAP_POSITIVE_X: |
| 390 | case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: |
| 391 | case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: |
| 392 | case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: |
| 393 | case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: |
| 394 | case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: |
| 395 | assert(GL_TEXTURE_CUBE_MAP == ctx->tex.tmus[ctx->tex.active]->type); |
| 396 | assert(width == height); |
| 397 | offset = (target - GL_TEXTURE_CUBE_MAP_POSITIVE_X) * size; |
| 398 | totalSize = 6 * size; |
| 399 | break; |
| 400 | default: |
| 401 | assert(0); |
| 402 | return; |
| 403 | } |
| 404 | |
| 405 | tex.levels = realloc(tex.levels, totalSize); |
| 406 | if (pixels) |
| 407 | CopyTexture((char *)tex.levels, (const char *)pixels, bytesPerPixel, 0, 0, width, 0, 0, width, width, height); |
| 408 | ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); |
| 409 | } |
| 410 | |
| 411 | void glTexParameterf(GLenum target, GLenum pname, GLfloat param) |
| 412 | { |
| 413 | // LOGD("agl2: glTexParameterf target=0x%.4X pname=0x%.4X param=%f", target, pname, param); |
| 414 | glTexParameteri(target, pname, param); |
| 415 | } |
| 416 | void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params) |
| 417 | { |
| 418 | CALL_GL_API(glTexParameterfv, target, pname, params); |
| 419 | } |
| 420 | void glTexParameteri(GLenum target, GLenum pname, GLint param) |
| 421 | { |
| 422 | GLES2_GET_CONST_CONTEXT(ctx); |
| 423 | // LOGD("alg2: glTexParameteri target=0x%.0X pname=0x%.4X param=0x%.4X", |
| 424 | // target, pname, param); |
| 425 | assert(ctx->tex.tmus[ctx->tex.active]); |
| 426 | assert(target == ctx->tex.tmus[ctx->tex.active]->type); |
| 427 | GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active]; |
| 428 | switch (pname) { |
| 429 | case GL_TEXTURE_WRAP_S: |
| 430 | case GL_TEXTURE_WRAP_T: |
| 431 | GGLTexture::GGLTextureWrap wrap; |
| 432 | switch (param) { |
| 433 | case GL_REPEAT: |
| 434 | wrap = GGLTexture::GGL_REPEAT; |
| 435 | break; |
| 436 | case GL_CLAMP_TO_EDGE: |
| 437 | wrap = GGLTexture::GGL_CLAMP_TO_EDGE; |
| 438 | break; |
| 439 | case GL_MIRRORED_REPEAT: |
| 440 | wrap = GGLTexture::GGL_MIRRORED_REPEAT; |
| 441 | break; |
| 442 | default: |
| 443 | assert(0); |
| 444 | return; |
| 445 | } |
| 446 | if (GL_TEXTURE_WRAP_S == pname) |
| 447 | tex.wrapS = wrap; |
| 448 | else |
| 449 | tex.wrapT = wrap; |
| 450 | break; |
| 451 | case GL_TEXTURE_MIN_FILTER: |
| 452 | switch (param) { |
| 453 | case GL_NEAREST: |
| 454 | tex.minFilter = GGLTexture::GGL_NEAREST; |
| 455 | break; |
| 456 | case GL_LINEAR: |
| 457 | tex.minFilter = GGLTexture::GGL_LINEAR; |
| 458 | break; |
| 459 | case GL_NEAREST_MIPMAP_NEAREST: |
| 460 | // tex.minFilter = GGLTexture::GGL_NEAREST_MIPMAP_NEAREST; |
| 461 | break; |
| 462 | case GL_NEAREST_MIPMAP_LINEAR: |
| 463 | // tex.minFilter = GGLTexture::GGL_NEAREST_MIPMAP_LINEAR; |
| 464 | break; |
| 465 | case GL_LINEAR_MIPMAP_NEAREST: |
| 466 | // tex.minFilter = GGLTexture::GGL_LINEAR_MIPMAP_NEAREST; |
| 467 | break; |
| 468 | case GL_LINEAR_MIPMAP_LINEAR: |
| 469 | // tex.minFilter = GGLTexture::GGL_LINEAR_MIPMAP_LINEAR; |
| 470 | break; |
| 471 | default: |
| 472 | assert(0); |
| 473 | return; |
| 474 | } |
| 475 | break; |
| 476 | case GL_TEXTURE_MAG_FILTER: |
| 477 | switch (param) { |
| 478 | case GL_NEAREST: |
| 479 | tex.minFilter = GGLTexture::GGL_NEAREST; |
| 480 | break; |
| 481 | case GL_LINEAR: |
| 482 | tex.minFilter = GGLTexture::GGL_LINEAR; |
| 483 | break; |
| 484 | default: |
| 485 | assert(0); |
| 486 | return; |
| 487 | } |
| 488 | break; |
| 489 | default: |
| 490 | assert(0); |
| 491 | return; |
| 492 | } |
| 493 | // implementation restriction |
| 494 | if (tex.magFilter != tex.minFilter) |
| 495 | tex.magFilter = tex.minFilter = GGLTexture::GGL_LINEAR; |
| 496 | ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); |
| 497 | } |
| 498 | void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) |
| 499 | { |
| 500 | CALL_GL_API(glTexParameteriv, target, pname, params); |
| 501 | } |
| 502 | void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) |
| 503 | { |
| 504 | GLES2_GET_CONST_CONTEXT(ctx); |
| 505 | // LOGD("agl2: glTexSubImage2D target=0x%.4X level=%d xoffset=%d yoffset=%d width=%d height=%d format=0x%.4X type=0x%.4X pixels=%p", |
| 506 | // target, level, xoffset, yoffset, width, height, format, type, pixels); |
| 507 | assert(0 == level); |
| 508 | assert(target == ctx->tex.tmus[ctx->tex.active]->type); |
| 509 | switch (type) { |
| 510 | case GL_UNSIGNED_BYTE: |
| 511 | break; |
| 512 | case GL_UNSIGNED_SHORT_5_6_5: |
| 513 | format = GL_UNSIGNED_SHORT_5_6_5; |
| 514 | assert(4 == ctx->tex.unpack); |
| 515 | break; |
| 516 | default: |
| 517 | assert(0); |
| 518 | } |
| 519 | GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active]; |
| 520 | GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN; |
| 521 | unsigned bytesPerPixel = 0; |
| 522 | GetFormatAndBytesPerPixel(format, &bytesPerPixel, &texFormat); |
| 523 | assert(texFormat == tex.format); |
| 524 | assert(GL_UNSIGNED_BYTE == type); |
| 525 | switch (target) { |
| 526 | case GL_TEXTURE_2D: |
| 527 | CopyTexture((char *)tex.levels, (const char *)pixels, bytesPerPixel, 0, 0, width, xoffset, |
| 528 | yoffset, tex.width, width, height); |
| 529 | break; |
| 530 | default: |
| 531 | assert(0); |
| 532 | } |
| 533 | ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active); |
| 534 | } |