KDvoid CCTextureAtlas::moveQuadsFromIndex ( KDuint uOldIndex, KDuint uAmount, KDuint uNewIndex ) { CCAssert ( uNewIndex + uAmount <= m_uTotalQuads, "insertQuadFromIndex:atIndex: Invalid index" ); CCAssert ( uOldIndex < m_uTotalQuads, "insertQuadFromIndex:atIndex: Invalid index" ); if ( uOldIndex == uNewIndex ) { return; } //create buffer KDsize nQuadSize = sizeof ( ccV3F_C4B_T2F_Quad ); ccV3F_C4B_T2F_Quad* pTempQuads = (ccV3F_C4B_T2F_Quad*) kdMalloc ( nQuadSize * uAmount ); kdMemcpy ( pTempQuads, &m_pQuads [ uOldIndex ], nQuadSize * uAmount ); if ( uNewIndex < uOldIndex ) { // move quads from newIndex to newIndex + amount to make room for buffer kdMemmove ( &m_pQuads [ uNewIndex ], &m_pQuads [ uNewIndex + uAmount ], ( uOldIndex - uNewIndex ) * nQuadSize ); } else { // move quads above back kdMemmove ( &m_pQuads [ uOldIndex ], &m_pQuads [ uOldIndex + uAmount ], ( uNewIndex - uOldIndex ) * nQuadSize ); } kdMemcpy ( &m_pQuads [ uNewIndex ], pTempQuads, uAmount * nQuadSize ); kdFree ( pTempQuads ); m_bDirty = KD_TRUE; }
static void __kdExtractBlock(const KDuint8 *src, KDint32 x, KDint32 y, KDint32 w, KDint32 h, KDuint8 *block) { if((w - x >= 4) && (h - y >= 4)) { /* Full Square shortcut */ src += x * 4; src += y * w * 4; for(KDint i = 0; i < 4; ++i) { kdMemcpy(block, src, sizeof(KDuint8)); block += 4; src += 4; kdMemcpy(block, src, sizeof(KDuint8)); block += 4; src += 4; kdMemcpy(block, src, sizeof(KDuint8)); block += 4; src += 4; kdMemcpy(block, src, sizeof(KDuint8)); block += 4; src += (w * 4) - 12; } return; } KDint32 bw = kdMinVEN(w - x, 4); KDint32 bh = kdMinVEN(h - y, 4); const KDint32 rem[] = { 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 2, 0, 0, 1, 2, 3}; for(KDint i = 0; i < 4; ++i) { KDint32 by = rem[(bh - 1) * 4 + i] + y; for(KDint j = 0; j < 4; ++j) { KDint32 bx = rem[(bw - 1) * 4 + j] + x; block[(i * 4 * 4) + (j * 4) + 0] = src[(by * (w * 4)) + (bx * 4) + 0]; block[(i * 4 * 4) + (j * 4) + 1] = src[(by * (w * 4)) + (bx * 4) + 1]; block[(i * 4 * 4) + (j * 4) + 2] = src[(by * (w * 4)) + (bx * 4) + 2]; block[(i * 4 * 4) + (j * 4) + 3] = src[(by * (w * 4)) + (bx * 4) + 3]; } } }
KDvoid M3GImage2D::set ( KDint x, KDint y, KDint width, KDint height, const KDubyte* image ) { if ( m_bImmutable ) { M3GException ( "IllegalStateException", __FUNCTION__, "This image is immutable." ); } if ( x < 0 || y >= m_nWidth || y < 0 || y >= m_nHeight ) { M3GException ( "IllegalArgumentException", __FUNCTION__, "Coordinate ( x, y ) is invalid, x = %d, y = %d.", x, y ); } if ( width < 0 || width > m_nWidth || height < 0 || height > m_nHeight ) { M3GException ( "IllegalArgumentException", __FUNCTION__, "Size ( width, height ) is invalid, width = %d, height = %d.", width, height ); } if ( image == KD_NULL ) { M3GException ( "NullPointerException", __FUNCTION__, "Image is NULL." ); } KDint nBpp = m3gGetBpp ( m_nFormat ); for ( KDint j = y; j < y + height; j++ ) { kdMemcpy ( m_pImage + j * m_nWidth * nBpp + x * nBpp, (KDchar*) image + ( j - y ) * width * nBpp, width * nBpp ); } }
kmVec4* kmVec4Assign(kmVec4* pOut, const kmVec4* pIn) { kdAssert(pOut != pIn); kdMemcpy(pOut, pIn, sizeof(float) * 4); return pOut; }
KDint xmReadRowsTIFF ( KDFile* file, XMImage* image ) { TIFFDecode* decode = (TIFFDecode*) image->decode; kdMemcpy ( image->rows, &decode->pixels[ decode->row_count * image->width ], image->width * sizeof (KDuint32) ); decode->row_count++; return 0; }
KDvoid M3GVertexArray::get ( KDint firstVertex, KDint numVertices, KDint valueSize, KDvoid* values ) const { if ( values == KD_NULL ) { M3GException ( "NullPointerException", __FUNCTION__ , "Values is NULL." ); } if ( firstVertex < 0 || firstVertex >= m_nVertexCount ) { M3GException ( "IllegalArgumentException", __FUNCTION__, "First vertex is invalid, firstVertex = %d.", firstVertex ); } if ( numVertices < 0 || firstVertex + numVertices > m_nVertexCount ) { M3GException ( "IllegalArgumentException", __FUNCTION__, "Number of vertices is Invalid, firstVertex = %d, numVertices = %d.", firstVertex, numVertices ); } if ( m_nComponentSize != valueSize ) { M3GException ( "IllegalStateException", __FUNCTION__ , "Component size of this vertex array is not %d byte, componentSize = %d.", m_nComponentSize, valueSize ); } KDint nOffset = firstVertex * m_nComponentCount * valueSize; KDint nSize = numVertices * m_nComponentCount * valueSize; kdMemcpy ( values, &m_pValues8 [ nOffset ], nSize ); }
KDbool Image::initWithRawData ( const KDubyte* pData, KDint32 nDataLen, KDint32 nWidth, KDint32 nHeight, KDint32 nBitsPerComponent, KDbool bPreMulti ) { KDbool bRet = false; do { CC_BREAK_IF ( 0 == nWidth || 0 == nHeight ); m_nHeight = nHeight; m_nWidth = nWidth; m_bPreMulti = bPreMulti; m_bHasPremultipliedAlpha = bPreMulti; switch ( nBitsPerComponent ) { case 8 : m_eRenderFormat = Texture2D::PixelFormat::I8; break; case 16 : m_eRenderFormat = Texture2D::PixelFormat::AI88; break; case 24 : m_eRenderFormat = Texture2D::PixelFormat::RGB888; break; case 32 : m_eRenderFormat = Texture2D::PixelFormat::RGBA8888; break; default : CCAssert ( false, "Not Support BitsPerComponent" ); } // only RGBA8888 supported KDint bytesPerComponent = nBitsPerComponent >> 3; m_nDataLen = nHeight * nWidth * bytesPerComponent; m_pData = new KDubyte [ m_nDataLen ]; CC_BREAK_IF ( !m_pData ); kdMemcpy ( m_pData, pData, m_nDataLen ); bRet = true; } while ( 0 ); return bRet; }
KDint xmReadRowsETC ( KDFile* file, XMImage* image ) { ETCDecode* decode = (ETCDecode*) image->decode; kdMemcpy ( image->rows, &decode->pixels[ decode->row_count * image->ptr_tile->stride ], image->ptr_tile->stride ); decode->row_count++; return 0; }
// kdThreadOnce : Wrap initialization code so it is executed only once. KD_API KDint KD_APIENTRY kdThreadOnce ( KDThreadOnce *once_control, KDvoid (* init_routine) ( KDvoid ) ) { if ( !once_control->impl ) { pthread_once_t ponce = PTHREAD_ONCE_INIT; once_control->impl = kdMalloc ( sizeof ( pthread_once_t ) ); kdMemcpy ( once_control->impl, (const KDvoid *) &ponce, sizeof ( pthread_once_t ) ); } return pthread_once ( (pthread_once_t *) once_control->impl, init_routine ); }
KDvoid M3GImage2D::init ( KDint format, KDint width, KDint height, KDubyte* pixels, KDubyte* palette ) { m_nFormat = format; m_nWidth = width; m_nHeight = height; KDint nBpp = m3gGetBpp ( format ); KDint nLength = height * width * nBpp; m_pImage = new KDubyte [ nLength ]; if ( pixels ) { m_bImmutable = KD_TRUE; if ( palette ) { for ( KDint y = 0; y < height; y++ ) { for ( KDint x = 0; x < width; x++ ) { KDint nIndex = pixels [ y * width + x ]; kdMemcpy ( m_pImage + ( y * width + x ) * nBpp, (KDubyte*) palette + nIndex * nBpp, nBpp ); } } } else { kdMemcpy ( m_pImage, pixels, nLength ); } } else { kdMemset ( m_pImage, 0, nLength ); } }
KDvoid M3GVertexArray::set ( KDint firstVertex, KDint numVertices, KDint valueSize, const KDvoid* values ) { if ( values == KD_NULL ) { M3GException ( "NullPointerException", __FUNCTION__ , "Values is NULL." ); } if ( numVertices < 0 ) { M3GException ( "IllegalArgumentException", __FUNCTION__, "Number of vertices is invalid, numVertices = %d.", numVertices ); } if ( firstVertex < 0 || firstVertex + numVertices > m_nVertexCount ) { M3GException ( "IndexOutOfBoundsException", __FUNCTION__, "Vertex is out of bounds, [%d, %d] in [0, %d].", firstVertex, firstVertex + numVertices, m_nVertexCount ); } if ( m_nComponentSize != valueSize ) { M3GException ( "IllegalStateException", __FUNCTION__ , "Component size of this vertex array is not %d byte, componentSize = %d.", m_nComponentSize, valueSize ); } if ( m_uID == 0 ) { M3GException ( "OpenGLException", __FUNCTION__, "Vertex Buffre Object is not ready." ); } KDint nOffset = firstVertex * m_nComponentCount * valueSize; KDint nSize = numVertices * m_nComponentCount * valueSize; kdMemcpy ( &m_pValues8 [ nOffset ], values, nSize ); glBindBuffer ( GL_ARRAY_BUFFER, m_uID ); glBufferSubData ( GL_ARRAY_BUFFER, nOffset, nSize, &m_pValues8 [ nOffset ] ); GLenum nErr = glGetError ( ); if ( nErr != GL_NO_ERROR ) { M3GException ( "OpenGLException", __FUNCTION__, "Can't send to GPU, err = %d.", nErr ); } }
// Allocate a node from the pool. Grow the pool if necessary. int32 b2DynamicTree::AllocateNode() { // Expand the node pool as needed. if (m_freeList == b2_nullNode) { b2Assert(m_nodeCount == m_nodeCapacity); // The free list is empty. Rebuild a bigger pool. b2TreeNode* oldNodes = m_nodes; m_nodeCapacity *= 2; m_nodes = (b2TreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2TreeNode)); kdMemcpy(m_nodes, oldNodes, m_nodeCount * sizeof(b2TreeNode)); b2Free(oldNodes); // Build a linked list for the free list. The parent // pointer becomes the "next" pointer. for (int32 i = m_nodeCount; i < m_nodeCapacity - 1; ++i) { m_nodes[i].next = i + 1; m_nodes[i].height = -1; } m_nodes[m_nodeCapacity-1].next = b2_nullNode; m_nodes[m_nodeCapacity-1].height = -1; m_freeList = m_nodeCount; } // Peel a node off the free list. int32 nodeId = m_freeList; m_freeList = m_nodes[nodeId].next; m_nodes[nodeId].parent = b2_nullNode; m_nodes[nodeId].child1 = b2_nullNode; m_nodes[nodeId].child2 = b2_nullNode; m_nodes[nodeId].height = 0; m_nodes[nodeId].userData = NULL; ++m_nodeCount; return nodeId; }
// kdThreadMutexCreate : Create a mutex. KD_API KDThreadMutex* KD_APIENTRY kdThreadMutexCreate ( const KDvoid* mutexattr ) { pthread_mutex_t pmutex = PTHREAD_MUTEX_INITIALIZER; KDThreadMutex* mutex = 0; KDint ret = 0; if ( ( mutex = (KDThreadMutex *) kdMalloc ( sizeof ( KDThreadMutex ) ) ) ) { kdMemcpy ( &mutex->pmutex, &pmutex, sizeof ( pthread_mutex_t ) ); if ( ( ret = pthread_mutex_init ( &mutex->pmutex, (const pthread_mutexattr_t *) mutexattr ) ) ) { kdSetError ( ret == ENOMEM ? KD_ENOMEM : KD_EAGAIN ); kdFree ( mutex ); mutex = 0; } } else { kdSetError ( KD_ENOMEM ); } return mutex; }
// kdThreadCondCreate : Create a condition variable. KD_API KDThreadCond* KD_APIENTRY kdThreadCondCreate ( const KDvoid* attr ) { pthread_cond_t pcond = PTHREAD_COND_INITIALIZER; KDThreadCond* cond = 0; KDint ret = 0; if ( ( cond = (KDThreadCond *) kdMalloc ( sizeof ( KDThreadCond ) ) ) ) { kdMemcpy ( &cond->pcond, &pcond, sizeof ( pthread_cond_t ) ); if ( ( ret = pthread_cond_init ( &cond->pcond, (const pthread_condattr_t *) attr) ) ) { kdSetError ( ret == ENOMEM ? KD_ENOMEM : KD_EAGAIN ); kdFree ( cond ); cond = 0; } } else { kdSetError ( KD_ENOMEM ); } return cond; }
KD_API KDImageATX KD_APIENTRY kdDXTCompressBufferATX(const void *buffer, KDint32 width, KDint32 height, KDint32 comptype, KDint32 levels) { _KDImageATX *image = (_KDImageATX *)kdMalloc(sizeof(_KDImageATX)); if(image == KD_NULL) { kdSetError(KD_ENOMEM); return KD_NULL; } image->levels = levels; image->width = width; image->height = height; switch(comptype) { case(KD_DXTCOMP_TYPE_DXT1_ATX): { image->format = KD_IMAGE_FORMAT_DXT1_ATX; image->alpha = KD_FALSE; break; } case(KD_DXTCOMP_TYPE_DXT1A_ATX): { kdFree(image); kdSetError(KD_EINVAL); return KD_NULL; } case(KD_DXTCOMP_TYPE_DXT3_ATX): { kdFree(image); kdSetError(KD_EINVAL); return KD_NULL; } case(KD_DXTCOMP_TYPE_DXT5_ATX): { image->format = KD_IMAGE_FORMAT_DXT5_ATX; image->alpha = KD_TRUE; break; } default: { kdFree(image); kdSetError(KD_EINVAL); return KD_NULL; } } image->bpp = image->alpha ? 16 : 8; image->size = (KDsize)image->width * (KDsize)image->height * (KDsize)(image->bpp / 8); KDint _width = image->width; KDint _height = image->height; for(KDint i = 0; i < image->levels; i++) { _width >>= 1; _height >>= 1; image->size += (KDsize)_width * (KDsize)_height * (KDsize)(image->bpp / 8); } image->buffer = kdMalloc(image->size); if(image->buffer == KD_NULL) { kdFree(image); kdSetError(KD_ENOMEM); return KD_NULL; } _width = image->width; _height = image->height; KDint channels = (image->alpha ? 4 : 3); for(KDint i = 0; i <= image->levels; i++) { KDsize size = (KDsize)_width * (KDsize)_height * (KDsize)channels; if(size) { void *tmp = kdMalloc(size); if((_width == image->width) && (_height == image->height)) { kdMemcpy(tmp, buffer, size); } else { stbir_resize_uint8(buffer, image->width, image->height, 0, tmp, _width, _height, 0, channels); } for(KDint y = 0; y < _height; y += 4) { for(KDint x = 0; x < _width; x += 4) { KDuint8 block[64]; __kdExtractBlock(tmp, x, y, _width, _height, block); stb_compress_dxt_block(image->buffer, block, image->alpha, STB_DXT_NORMAL); image->buffer += image->bpp; } } kdFree(tmp); } _width >>= 1; _height >>= 1; } return image; }
KD_API KDImageATX KD_APIENTRY kdGetImageFromStreamATX(KDFile *file, KDint format, KDint flags) { _KDImageATX *image = (_KDImageATX *)kdMalloc(sizeof(_KDImageATX)); if(image == KD_NULL) { kdSetError(KD_ENOMEM); return KD_NULL; } image->levels = 0; image->bpp = 8; KDStat st; if(kdFstat(file, &st) == -1) { kdFree(image); kdSetError(KD_EIO); return KD_NULL; } void *filedata = kdMalloc((KDsize)st.st_size); if(filedata == KD_NULL) { kdFree(image); kdSetError(KD_ENOMEM); return KD_NULL; } if(kdFread(filedata, 1, (KDsize)st.st_size, file) != (KDsize)st.st_size) { kdFree(filedata); kdFree(image); kdSetError(KD_EIO); return KD_NULL; } if(kdFseek(file, 0, KD_SEEK_SET) == -1) { kdFree(filedata); kdFree(image); kdSetError(KD_EIO); return KD_NULL; } KDint channels = 0; image->format = format; switch(image->format) { case(KD_IMAGE_FORMAT_RGBA8888_ATX): { channels = 4; image->alpha = KD_TRUE; break; } case(KD_IMAGE_FORMAT_RGB888_ATX): { channels = 3; image->alpha = KD_FALSE; break; } case(KD_IMAGE_FORMAT_LUMALPHA88_ATX): { channels = 2; image->alpha = KD_TRUE; break; } case(KD_IMAGE_FORMAT_LUM8_ATX): { channels = 1; image->alpha = KD_FALSE; break; } case(KD_IMAGE_FORMAT_COMPRESSED_ATX): { /* TODO: Load compressed formats (do not decode) */ } default: { kdFree(filedata); kdFree(image); kdSetError(KD_EINVAL); return KD_NULL; } } if(kdStrstrVEN(file->pathname, ".pvr")) { if(channels == 4) { /* PVR v2 only*/ struct PVR_Texture_Header { KDuint dwHeaderSize; /* size of the structure */ KDuint dwHeight; /* height of surface to be created */ KDuint dwWidth; /* width of input surface */ KDuint dwMipMapCount; /* number of mip-map levels requested */ KDuint dwpfFlags; /* pixel format flags */ KDuint dwTextureDataSize; /* Total size in bytes */ KDuint dwBitCount; /* number of bits per pixel */ KDuint dwRBitMask; /* mask for red bit */ KDuint dwGBitMask; /* mask for green bits */ KDuint dwBBitMask; /* mask for blue bits */ KDuint dwAlphaBitMask; /* mask for alpha channel */ KDuint dwPVR; /* magic number identifying pvr file */ KDuint dwNumSurfs; /* the number of surfaces present in the pvr */ }; struct PVR_Texture_Header header; kdMemcpy(&header, filedata, sizeof(KDuint) * 13); image->height = (KDint)header.dwHeight; image->width = (KDint)header.dwWidth; image->size = (KDsize)image->width * (KDsize)image->height * (KDsize)channels * sizeof(KDuint); image->buffer = kdMalloc(image->size); /* PVRCT2/4 RGB/RGBA compressed formats for now */ __kdDecompressPVRTC((const KDuint8 *)filedata + header.dwHeaderSize, 0, image->width, image->height, image->buffer); } } else { if(flags == KD_IMAGE_FLAG_FLIP_X_ATX) { stbi_set_flip_vertically_on_load(1); } image->buffer = stbi_load_from_memory(filedata, (KDint)st.st_size, &image->width, &image->height, (KDint[]) {0}, channels); image->size = (KDsize)image->width * (KDsize)image->height * (KDsize)channels * sizeof(KDuint); } kdFree(filedata); if(image->buffer == KD_NULL) { kdLogMessagefKHR("%s.\n", stbi_failure_reason()); kdFree(image); kdSetError(KD_EILSEQ); return KD_NULL; } return image; }
KDvoid CCTextureAtlas::drawNumberOfQuads ( KDuint uNumber, KDuint uStart ) { if ( 0 == uNumber ) { return; } ccGLBindTexture2D ( m_pTexture->getName ( ) ); #if CC_TEXTURE_ATLAS_USE_VAO // // Using VBO and VAO // // XXX: update is done in draw... perhaps it should be done in a timer if ( m_bDirty ) { glBindBuffer ( GL_ARRAY_BUFFER, m_pBuffersVBO[0] ); // option 1: subdata // glBufferSubData ( GL_ARRAY_BUFFER, sizeof ( m_pQuads[0] ) * uStart, sizeof ( m_pQuads[0] ) * uNumber , &m_pQuads [ uStart ] ); // option 2: data // glBufferData ( GL_ARRAY_BUFFER, sizeof ( m_pQuads[0] ) * ( n - uStart ), &m_pQuads [ uStart ], GL_DYNAMIC_DRAW ); // option 3: orphaning + glMapBuffer glBufferData ( GL_ARRAY_BUFFER, sizeof ( m_pQuads[0] ) * ( n - uStart ), KD_NULL, GL_DYNAMIC_DRAW ); KDvoid* pBuff = glMapBuffer ( GL_ARRAY_BUFFER, GL_WRITE_ONLY ); kdMemcpy ( pBuff, m_pQuads, sizeof ( m_pQuads [ 0 ] ) * ( n - uStart ) ); glUnmapBuffer ( GL_ARRAY_BUFFER ); glBindBuffer ( GL_ARRAY_BUFFER, 0 ); m_bDirty = KD_FALSE; } ccGLBindVAO ( m_uVAOname ); #if CC_REBIND_INDICES_BUFFER glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1] ); #endif glDrawElements ( GL_TRIANGLES, (GLsizei) uNumber * 6, GL_UNSIGNED_SHORT, (GLvoid*) ( uStart * 6 * sizeof ( m_pIndices[0] ) ) ); #if CC_REBIND_INDICES_BUFFER glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, 0 ); #endif // glBindVertexArray ( 0 ); #else // CC_TEXTURE_ATLAS_USE_VAO // // Using VBO without VAO // #define kQuadSize sizeof(m_pQuads[0].bl) glBindBuffer ( GL_ARRAY_BUFFER, m_pBuffersVBO[0] ); // XXX: update is done in draw... perhaps it should be done in a timer if ( m_bDirty ) { glBufferSubData ( GL_ARRAY_BUFFER, sizeof ( m_pQuads[0] ) * uStart, sizeof ( m_pQuads[0] ) * uNumber , &m_pQuads[ uStart ] ); m_bDirty = KD_FALSE; } ccGLEnableVertexAttribs ( kCCVertexAttribFlag_PosColorTex ); ccGLVertexAttribPointer ( kCCVertexAttrib_Position , 3, GL_FLOAT , GL_FALSE, kQuadSize, (GLvoid*) offsetof ( ccV3F_C4B_T2F, vertices ) ); ccGLVertexAttribPointer ( kCCVertexAttrib_Color , 4, GL_UNSIGNED_BYTE, GL_TRUE , kQuadSize, (GLvoid*) offsetof ( ccV3F_C4B_T2F, colors ) ); ccGLVertexAttribPointer ( kCCVertexAttrib_TexCoords, 2, GL_FLOAT , GL_FALSE, kQuadSize, (GLvoid*) offsetof ( ccV3F_C4B_T2F, texCoords ) ); glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, m_pBuffersVBO[1] ); glDrawElements ( GL_TRIANGLES, (GLsizei) uNumber * 6, GL_UNSIGNED_SHORT, (GLvoid*) ( uStart * 6 * sizeof ( m_pIndices[0] ) ) ); glBindBuffer ( GL_ARRAY_BUFFER, 0 ); glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER, 0 ); #endif // CC_TEXTURE_ATLAS_USE_VAO CC_INCREMENT_GL_DRAWS ( 1 ); CHECK_GL_ERROR_DEBUG ( ); }