| 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 | } |