diff --git a/GL/draw.c b/GL/draw.c index 4d48169..0a66e45 100644 --- a/GL/draw.c +++ b/GL/draw.c @@ -1031,7 +1031,8 @@ static void submitVertices(GLenum mode, GLsizei first, GLuint count, GLenum type } /* No vertices? Do nothing */ - if(!count) { + //changed check + if(count < 3) { return; } @@ -1085,9 +1086,15 @@ static void submitVertices(GLenum mode, GLsizei first, GLuint count, GLenum type target->output = _glActivePolyList(); target->count = (mode == GL_TRIANGLE_FAN) ? ((count - 2) * 3) : count; + if(target->count < 3 || count < 3){ + printf("%s: %d = %u verts\n",__func__,count,target->count); + } target->header_offset = target->output->vector.size; target->start_offset = target->header_offset + 1; + if(target-count == 0){ + return; + } assert(target->count); /* Make sure we have enough room for all the "extra" data */ @@ -1207,8 +1214,8 @@ static void submitVertices(GLenum mode, GLsizei first, GLuint count, GLenum type glDepthFunc(GL_EQUAL); glEnable(GL_BLEND); - - /* This is modulation, we need to switch depending on the texture env mode! */ + + /* This is modulation, we need to switch depending on the texture env mode! */ glBlendFunc(GL_DST_COLOR, GL_ZERO); /* Send the buffer again to the transparent list */ @@ -1229,6 +1236,9 @@ void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvo if(_glCheckImmediateModeInactive(__func__)) { return; } + if(count < 3){ + return; + } submitVertices(mode, 0, count, type, indices); } @@ -1239,6 +1249,9 @@ void APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count) { if(_glCheckImmediateModeInactive(__func__)) { return; } + if(count < 3){ + return; + } submitVertices(mode, first, count, GL_UNSIGNED_INT, NULL); } diff --git a/GL/state.c b/GL/state.c index 61f3b74..aa55b65 100644 --- a/GL/state.c +++ b/GL/state.c @@ -18,6 +18,61 @@ pvr_poly_cxt_t* _glGetPVRContext() { return &GL_CONTEXT; } +static GLubyte mipmap_bias = 4; + +GLAPI void APIENTRY glKOS_INTERNAL_SetMipmapBias(GLubyte level) { + switch(level){ + case 1: + mipmap_bias = PVR_MIPBIAS_0_25; + break; + case 2: + mipmap_bias = PVR_MIPBIAS_0_50; + break; + case 3: + mipmap_bias = PVR_MIPBIAS_0_75; + break; + case 4: + mipmap_bias = PVR_MIPBIAS_1_00; + break; + case 5: + mipmap_bias = PVR_MIPBIAS_1_25; + break; + case 6: + mipmap_bias = PVR_MIPBIAS_1_50; + break; + case 7: + mipmap_bias = PVR_MIPBIAS_1_75; + break; + case 8: + mipmap_bias = PVR_MIPBIAS_2_00; + break; + case 9: + mipmap_bias = PVR_MIPBIAS_2_25; + break; + case 10: + mipmap_bias = PVR_MIPBIAS_2_50; + break; + case 11: + mipmap_bias = PVR_MIPBIAS_2_75; + break; + case 12: + mipmap_bias = PVR_MIPBIAS_3_00; + break; + case 13: + mipmap_bias = PVR_MIPBIAS_3_25; + break; + case 14: + mipmap_bias = PVR_MIPBIAS_3_50; + break; + case 15: + mipmap_bias = PVR_MIPBIAS_3_75; + break; + default: + mipmap_bias = PVR_MIPBIAS_1_00; + break; + } +} + /* We can't just use the GL_CONTEXT for this state as the two * GL states are combined, so we store them separately and then @@ -180,6 +235,10 @@ void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) { break; } + if(tx1->height != tx1->width){ + enableMipmaps = GL_FALSE; + } + /* FIXME: If you disable mipmaps on a compressed mipmapped texture * you get corruption and I don't know why, so we force mipmapping for now */ if(tx1->isCompressed && _glIsMipmapComplete(tx1)) { @@ -216,16 +275,24 @@ void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) { context->txr.enable = PVR_TEXTURE_ENABLE; context->txr.filter = filter; context->txr.mipmap = (enableMipmaps) ? PVR_MIPMAP_ENABLE : PVR_MIPMAP_DISABLE; - context->txr.mipmap_bias = PVR_MIPBIAS_NORMAL; + context->txr.mipmap_bias = mipmap_bias; context->txr.width = tx1->width; context->txr.height = tx1->height; - context->txr.base = tx1->data; + if(enableMipmaps){ + context->txr.base = tx1->data; + } else { + context->txr.base = _glGetMipmapLocation((TextureObject*)tx1,0); + } + context->txr.format = tx1->color; if(tx1->isPaletted) { if(_glIsSharedTexturePaletteEnabled()) { - TexturePalette* palette = _glGetSharedPalette(tx1->shared_bank); - context->txr.format |= PVR_TXRFMT_8BPP_PAL(palette->bank); + //TexturePalette* palette = _glGetSharedPalette(tx1->shared_bank); + context->txr.format |= PVR_TXRFMT_8BPP_PAL(tx1->shared_bank); + if(tx1->shared_bank != 0){ + //printf("%s chose bank %d!\n",__func__,tx1->shared_bank); + } } else { context->txr.format |= PVR_TXRFMT_8BPP_PAL((tx1->palette) ? tx1->palette->bank : 0); } diff --git a/GL/texture.c b/GL/texture.c index c8d0202..b7db324 100644 --- a/GL/texture.c +++ b/GL/texture.c @@ -166,21 +166,75 @@ static GLint _determineStride(GLenum format, GLenum type) { GLubyte* _glGetMipmapLocation(TextureObject* obj, GLuint level) { GLuint offset = 0; + if(obj->width == obj->height){ - GLuint i = 0; - GLuint width = obj->width; - GLuint height = obj->height; + if(obj->isPaletted){ + GLuint size = obj->height; - for(; i < level; ++i) { - offset += (width * height * obj->dataStride); + switch(size >> level){ + case 256: + offset = 0x05558; + break; + case 128: + offset = 0x01558; + break; + case 64: + offset = 0x00558; + break; + case 32: + offset = 0x00158; + break; + case 16: + offset = 0x00058; + break; + case 8: + offset = 0x00018; + break; + case 4: + offset = 0x00008; + break; + case 2: + offset = 0x00004; + break; + case 1: + case 0: + offset = 0x00000; + break; + } + } else { + GLuint size = obj->height; - if(width > 1) { - width /= 2; - } - - if(height > 1) { - height /= 2; - } + switch(size >> level){ + case 256: + offset = 0x0AAB0; + break; + case 128: + offset = 0x02AB0; + break; + case 64: + offset = 0x00AB0; + break; + case 32: + offset = 0x002B0; + break; + case 16: + offset = 0x000B0; + break; + case 8: + offset = 0x00030; + break; + case 4: + offset = 0x00010; + break; + case 2: + offset = 0x00008; + break; + case 1: + offset = 0x00006; + break; + } + + } } return ((GLubyte*) obj->data) + offset; @@ -197,7 +251,7 @@ static GLuint _glGetMipmapDataSize(TextureObject* obj) { GLuint width = obj->width; GLuint height = obj->height; - for(; i < _glGetMipmapLevelCount(obj); ++i) { + for(; i < _glGetMipmapLevelCount(obj)+1; ++i) { size += (width * height * obj->dataStride); if(width > 1) { @@ -490,6 +544,8 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target, static GLint _cleanInternalFormat(GLint internalFormat) { switch (internalFormat) { + case GL_COLOR_INDEX4_EXT: + return GL_COLOR_INDEX4_EXT; case GL_COLOR_INDEX8_EXT: return GL_COLOR_INDEX8_EXT; case GL_ALPHA: @@ -612,6 +668,8 @@ static GLuint _determinePVRFormat(GLint internalFormat, GLenum type) { return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE; case GL_COLOR_INDEX8_EXT: return PVR_TXRFMT_PAL8BPP | PVR_TXRFMT_TWIDDLED; + case GL_COLOR_INDEX4_EXT: + return PVR_TXRFMT_PAL4BPP | PVR_TXRFMT_TWIDDLED; default: return 0; } @@ -762,15 +820,15 @@ GLboolean _glIsMipmapComplete(const TextureObject* obj) { if(!obj->mipmap || !obj->mipmapCount) { return GL_FALSE; } - + GLsizei i = 0; - for(; i < obj->mipmapCount; ++i) { - if((obj->mipmap & (1 << i)) == 0) { - return GL_FALSE; + for(; i < obj->mipmapCount-3; ++i) { + if((obj->mipmap & (1 << i)) == 1) { + return GL_TRUE; } } - return GL_TRUE; + return GL_FALSE; } #define TWIDTAB(x) ( (x&1)|((x&2)<<1)|((x&4)<<2)|((x&8)<<3)|((x&16)<<4)| \ @@ -810,16 +868,19 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, } GLint w = width; - if(w < 8 || (w & -w) != w) { + GLint h = height; + if(level == 0){ + if((w < 8 || (w & -w) != w)) { /* Width is not a power of two. Must be!*/ _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D"); } - GLint h = height; - if(h < 8 || (h & -h) != h) { + + if((h < 8 || (h & -h) != h)) { /* height is not a power of two. Must be!*/ _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D"); } + } if(level < 0) { _glKosThrowError(GL_INVALID_VALUE, "glTexImage2D"); @@ -835,11 +896,6 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLboolean isPaletted = (internalFormat == GL_COLOR_INDEX8_EXT) ? GL_TRUE : GL_FALSE; - if(isPaletted && level > 0) { - /* Paletted textures can't have mipmaps */ - _glKosThrowError(GL_INVALID_OPERATION, __func__); - } - if(_glKosHasError()) { _glKosPrintError(); return; @@ -852,7 +908,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, assert(active); - if(active->data) { + if(active->data && (level == 0) ) { /* pre-existing texture - check if changed */ if(active->width != width || active->height != height || @@ -946,11 +1002,18 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, min = MIN(w, h); mask = min - 1; + if(height == 1 || width == 1){ + targetData[0] = ((GLubyte*)data)[0]; + targetData[1] = ((GLubyte*)data)[0]; + targetData[2] = ((GLubyte*)data)[0]; + targetData[3] = ((GLubyte*)data)[0]; + } else { for(y = 0; y < h; y += 2) { for(x = 0; x < w; x++) { vtex[TWIDOUT((y & mask) / 2, x & mask) + (x / min + y / min)*min * min / 2] = pixels[y * w + x] | (pixels[(y + 1) * w + x] << 8); } } + } } else { /* No conversion? Just copy the data, and the pvr_format is correct */ sq_cpy(targetData, data, bytes); diff --git a/containers/named_array.c b/containers/named_array.c index 1127ddf..87b68c8 100644 --- a/containers/named_array.c +++ b/containers/named_array.c @@ -22,6 +22,7 @@ (byte & 0x04 ? '1' : '0'), \ (byte & 0x02 ? '1' : '0'), \ (byte & 0x01 ? '1' : '0') +#define assert__(x) for ( ; !(x) ; assert(x) ) void named_array_init(NamedArray* array, unsigned int element_size, unsigned int max_elements) { array->element_size = element_size; @@ -38,8 +39,8 @@ void named_array_init(NamedArray* array, unsigned int element_size, unsigned int array->elements = (unsigned char*) malloc(element_size * max_elements); array->used_markers = (unsigned char*) malloc(array->marker_count); #endif - //memset(array->used_markers, 0, sizeof(unsigned char) * array->marker_count); - sq_clr(array->used_markers, ((sizeof(unsigned char) * array->marker_count) & 0xfffffffc) + 4); + memset(array->used_markers, 0, sizeof(unsigned char) * array->marker_count); + memset(array->elements, 0, element_size * max_elements); } char named_array_used(NamedArray* array, unsigned int id) { @@ -76,6 +77,11 @@ void* named_array_reserve(NamedArray* array, unsigned int id) { unsigned int i = id / 8; array->used_markers[i] |= (unsigned char) 1 << j; + + assert__(named_array_used(array, id)) { + printf("%s: id %d is not used in [%d,%d] = "BYTE_TO_BINARY_PATTERN"\n",__func__,id,i,j, BYTE_TO_BINARY(array->used_markers[i])); + } + assert(named_array_used(array, id)); unsigned char* ptr = &array->elements[id * array->element_size]; diff --git a/include/glkos.h b/include/glkos.h index a7a675e..1e794c6 100644 --- a/include/glkos.h +++ b/include/glkos.h @@ -67,6 +67,8 @@ GLAPI void APIENTRY glKosInitConfig(GLdcConfig* config); GLAPI void APIENTRY glKosInitEx(GLdcConfig* config); GLAPI void APIENTRY glKosSwapBuffers(); +GLAPI void APIENTRY glKOS_INTERNAL_SetMipmapBias(GLubyte level); + /* * CUSTOM EXTENSION multiple_shared_palette_KOS *