gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Updating textures

#154128 - SiW - Fri Apr 11, 2008 7:49 pm

I'm having trouble getting my textures to update dynamically. I know the subject has come up before, but I'm making a new thread rather than digging up one from last year to make sure any discussion is on current practices.

I wait for vblank, then every ~2 seconds call this function:

Code:

void Jigsaw::UpdateFrame( int frame )
{
   u8 *img;
       
        [point img at the right bits for this frame]
   
   u8 *piece_color = new u8[tileSize]; // tileSize may be e.g. 128*128
   
   while ( (REG_VCOUNT < 192) || (REG_VCOUNT > 214) ) {}
   if ( (REG_VCOUNT >= 192) && (REG_VCOUNT <= 214) )
   {
      // unlock texture memory
      vramSetBankA( VRAM_A_LCD );
      vramSetBankB( VRAM_B_LCD );
            
      for ( int i = 0; i < numPieces; i++ )
      {         
         int width = 0;
         int height = 0;
                        [ get correct dimensions, e.g. TEXTURE_SIZE_64 ]
         
         [ modify piece_color ]
         
         // update gl info and copy texture data
         glBindTexture( GL_TEXTURE_2D, textureIDs[i] );   
         uint32* address = 0x06800000 + (uint32*)glGetTexturePointer( textureIDs[i] );
         
         glTexParameter( width, height, address, GL_RGB256, TEXGEN_TEXCOORD | GL_TEXTURE_COLOR0_TRANSPARENT );         
         
         dmaCopy( piece_color, address, tileSize );         
      }
      
                // lock texture memory again
      vramSetBankA( VRAM_A_TEXTURE );
      vramSetBankB( VRAM_B_TEXTURE );            
   }
   
   delete []piece_color;   
}


What happens is that my textured quads blink invisible when the function runs, but when they are visible again the original texture is displayed - no updating happens.

I presume I would avoid the blinking if I speed up my texture updating, but that's not my concern right now, I just want to get the texture animating.

So what am I doing wrong?

#154152 - TwentySeven - Sat Apr 12, 2008 12:07 am

I have code for this that works, its a bit of a hacked up version of the stuff out of libnds.

Code:

uint32 DSM_glTexImage2D( GL_TEXTURE_TYPE_ENUM type, int sizeX, int sizeY, int param, const uint8* texture, uint32 addr)
{

   uint32 size = 0;
   uint32 vramTemp;
   
   uint32 dims[]={8,16,32,64,128,256};

   size = 1 << (sizeX + sizeY + 6);

   switch (type) {
      case GL_RGB:
      case GL_RGBA:
         size = size << 1;
         break;
      case GL_RGB4:
         size = size >> 2;
         break;
      case GL_RGB16:
         size = size >> 1;
         break;
      default:
         break;
   }

   if(!addr)
   return 0;

   // unlock texture memory
   vramTemp = vramSetMainBanks(VRAM_A_LCD,VRAM_B_LCD,VRAM_C_LCD,VRAM_D_LCD);

   if (type == GL_RGB)
   {
      // We do GL_RGB as GL_RGBA, but we set each alpha bit to 1 during the copy
      u16 * src = (u16*)texture;
      u16 * dest = (u16*)addr;

      while (size--) {
         *dest++ = *src | (1 << 15);
         src++;
      }
   }
   else
   {
      uint16 part_size=0;
      if (type == GL_RGB256) part_size = ((dims[sizeX]*dims[sizeY])>>2);
      if (type == GL_RGBA) part_size = ((dims[sizeX]*dims[sizeY]*2)>>2);
      dmaCopyWordsAsynch(0, texture, (void*)addr, part_size);
      dmaCopyWordsAsynch(1, texture + part_size,   (void*)((int16*)addr + (part_size>>1)),   part_size );
      dmaCopyWordsAsynch(2, texture + part_size*2, (void*)((int16*)addr + (part_size>>1)*2), part_size );
      dmaCopyWords(      3, texture + part_size*3, (void*)((int16*)addr + (part_size>>1)*3), part_size );             
   }
   
   VRAM_CR = vramTemp;
   return addr;
}



You pass in the texture pointer to this. I'm also only using it with square textures.

#154153 - TwentySeven - Sat Apr 12, 2008 12:13 am

As for what the actual problem is, it looks suspiciously like you're running out of time to update your texture during vblank.

You have roughly 2ms to get your texture uploaded and the CR's set back to normal, so if you have any processing to do, do it before vblank.

If thats not it, are you binding your texture again after you're done uploading it? I don't remember the exact reasoning except for it possibly needing to be done twice.

Code:

glBindTexture(GL_TEXTURE_2D, TextureCache->Textures[j].Handle);
DSM_glTexImage2D( GL_RGBA, TEXTURE_SIZE_32 , TEXTURE_SIZE_32, 0, (byte*)point,TextureCache->Textures[j].Addr);   
glBindTexture(GL_TEXTURE_2D, TextureCache->Textures[j].Handle);
[/code]

#154168 - SiW - Sat Apr 12, 2008 2:51 am

Thanks for the function. I am binding again after updating the texture, so I'm not really sure what the problem is. I have no doubt that I'm running out of time, but even so I would expect to still see the texture change, wouldn't I? Just with possible image corruption?

I'll play around with your function, but I also tried coming at it from a different angle while trying to debug the problem. See, I actually need to update every texture in memory, so for testing purposes I just tried an update function that calls glResetTextures and then regenerates textures with glGenTextures/glBindTexture/glTexImage2D. That works, and I think it's actually fast enough for this particular application, so I may just stick with it.

#154170 - TwentySeven - Sat Apr 12, 2008 4:24 am

Yeah, my stuff just preallocates all of vram into N 32x32,64x64,128x128 textures at startup, and I just recycle texture slots using that above function. It's not as nice as a proper dynamically allocating system but it means I don't run into fragmentation issues either.