Skip to content

Commit

Permalink
add texture mirroring
Browse files Browse the repository at this point in the history
  • Loading branch information
vieux authored and DragonMinded committed Oct 26, 2019
1 parent 1557cd8 commit 00a6cc8
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 23 deletions.
20 changes: 12 additions & 8 deletions include/rdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ typedef enum
{
/** @brief Disable texture mirroring */
MIRROR_DISABLED,
/** @brief Enable texture mirroring */
MIRROR_ENABLED
/** @brief Enable texture mirroring on x axis */
MIRROR_X,
/** @brief Enable texture mirroring on y axis */
MIRROR_Y,
/** @brief Enable texture mirroring on both x & y axis */
MIRROR_XY
} mirror_t;

/**
Expand Down Expand Up @@ -66,12 +70,12 @@ void rdp_set_default_clipping( void );
void rdp_enable_primitive_fill( void );
void rdp_enable_blend_fill( void );
void rdp_enable_texture_copy( void );
uint32_t rdp_load_texture( uint32_t texslot, uint32_t texloc, mirror_t mirror_enabled, sprite_t *sprite );
uint32_t rdp_load_texture_stride( uint32_t texslot, uint32_t texloc, mirror_t mirror_enabled, sprite_t *sprite, int offset );
void rdp_draw_textured_rectangle( uint32_t texslot, int tx, int ty, int bx, int by );
void rdp_draw_textured_rectangle_scaled( uint32_t texslot, int tx, int ty, int bx, int by, double x_scale, double y_scale );
void rdp_draw_sprite( uint32_t texslot, int x, int y );
void rdp_draw_sprite_scaled( uint32_t texslot, int x, int y, double x_scale, double y_scale );
uint32_t rdp_load_texture( uint32_t texslot, uint32_t texloc, mirror_t mirror, sprite_t *sprite );
uint32_t rdp_load_texture_stride( uint32_t texslot, uint32_t texloc, mirror_t mirror, sprite_t *sprite, int offset );
void rdp_draw_textured_rectangle( uint32_t texslot, int tx, int ty, int bx, int by, mirror_t mirror );
void rdp_draw_textured_rectangle_scaled( uint32_t texslot, int tx, int ty, int bx, int by, double x_scale, double y_scale, mirror_t mirror );
void rdp_draw_sprite( uint32_t texslot, int x, int y , mirror_t mirror);
void rdp_draw_sprite_scaled( uint32_t texslot, int x, int y, double x_scale, double y_scale, mirror_t mirror);
void rdp_set_primitive_color( uint32_t color );
void rdp_set_blend_color( uint32_t color );
void rdp_draw_filled_rectangle( int tx, int ty, int bx, int by );
Expand Down
58 changes: 43 additions & 15 deletions src/rdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ typedef struct
uint32_t width;
/** @brief Height of the texture */
uint32_t height;
/** @brief Width of the texture rounded up to next power of 2 */
uint16_t real_width;
/** @brief Height of the texture rounded up to next power of 2 */
uint16_t real_height;
} sprite_cache;

extern uint32_t __bitdepth;
Expand Down Expand Up @@ -488,7 +492,7 @@ static uint32_t __rdp_load_texture( uint32_t texslot, uint32_t texloc, mirror_t
/* Instruct the RDP to copy the sprite data out */
__rdp_ringbuffer_queue( 0xF5000000 | ((sprite->bitdepth == 2) ? 0x00100000 : 0x00180000) |
(((((real_width / 8) + round_amount) * sprite->bitdepth) & 0x1FF) << 9) | ((texloc / 8) & 0x1FF) );
__rdp_ringbuffer_queue( ((texslot & 0x7) << 24) | (mirror_enabled == MIRROR_ENABLED ? 0x40100 : 0) | (hbits << 14 ) | (wbits << 4) );
__rdp_ringbuffer_queue( ((texslot & 0x7) << 24) | (mirror_enabled != MIRROR_DISABLED ? 0x40100 : 0) | (hbits << 14 ) | (wbits << 4) );
__rdp_ringbuffer_send();

/* Copying out only a chunk this time */
Expand All @@ -501,6 +505,8 @@ static uint32_t __rdp_load_texture( uint32_t texslot, uint32_t texloc, mirror_t
cache[texslot & 0x7].height = theight - 1;
cache[texslot & 0x7].s = sl;
cache[texslot & 0x7].t = tl;
cache[texslot & 0x7].real_width = real_width;
cache[texslot & 0x7].real_height = real_height;

/* Return the amount of texture memory consumed by this texture */
return ((real_width / 8) + round_amount) * 8 * real_height * sprite->bitdepth;
Expand All @@ -513,18 +519,18 @@ static uint32_t __rdp_load_texture( uint32_t texslot, uint32_t texloc, mirror_t
* The RDP texture slot to load this sprite into (0-7)
* @param[in] texloc
* The RDP TMEM offset to place the texture at
* @param[in] mirror_enabled
* @param[in] mirror
* Whether the sprite should be mirrored when displaying past boundaries
* @param[in] sprite
* Pointer to sprite structure to load the texture from
*
* @return The number of bytes consumed in RDP TMEM by loading this sprite
*/
uint32_t rdp_load_texture( uint32_t texslot, uint32_t texloc, mirror_t mirror_enabled, sprite_t *sprite )
uint32_t rdp_load_texture( uint32_t texslot, uint32_t texloc, mirror_t mirror, sprite_t *sprite )
{
if( !sprite ) { return 0; }

return __rdp_load_texture( texslot, texloc, mirror_enabled, sprite, 0, 0, sprite->width - 1, sprite->height - 1 );
return __rdp_load_texture( texslot, texloc, mirror, sprite, 0, 0, sprite->width - 1, sprite->height - 1 );
}

/**
Expand All @@ -547,7 +553,7 @@ uint32_t rdp_load_texture( uint32_t texslot, uint32_t texloc, mirror_t mirror_en
* The RDP texture slot to load this sprite into (0-7)
* @param[in] texloc
* The RDP TMEM offset to place the texture at
* @param[in] mirror_enabled
* @param[in] mirror
* Whether the sprite should be mirrored when displaying past boundaries
* @param[in] sprite
* Pointer to sprite structure to load the texture from
Expand All @@ -556,7 +562,7 @@ uint32_t rdp_load_texture( uint32_t texslot, uint32_t texloc, mirror_t mirror_en
*
* @return The number of bytes consumed in RDP TMEM by loading this sprite
*/
uint32_t rdp_load_texture_stride( uint32_t texslot, uint32_t texloc, mirror_t mirror_enabled, sprite_t *sprite, int offset )
uint32_t rdp_load_texture_stride( uint32_t texslot, uint32_t texloc, mirror_t mirror, sprite_t *sprite, int offset )
{
if( !sprite ) { return 0; }

Expand All @@ -569,7 +575,7 @@ uint32_t rdp_load_texture_stride( uint32_t texslot, uint32_t texloc, mirror_t mi
int sh = sl + twidth - 1;
int th = tl + theight - 1;

return __rdp_load_texture( texslot, texloc, mirror_enabled, sprite, sl, tl, sh, th );
return __rdp_load_texture( texslot, texloc, mirror, sprite, sl, tl, sh, th );
}

/**
Expand Down Expand Up @@ -597,25 +603,41 @@ uint32_t rdp_load_texture_stride( uint32_t texslot, uint32_t texloc, mirror_t mi
* Horizontal scaling factor
* @param[in] y_scale
* Vertical scaling factor
* @param[in] mirror
* Whether the texture should be mirrored
*/
void rdp_draw_textured_rectangle_scaled( uint32_t texslot, int tx, int ty, int bx, int by, double x_scale, double y_scale )
void rdp_draw_textured_rectangle_scaled( uint32_t texslot, int tx, int ty, int bx, int by, double x_scale, double y_scale, mirror_t mirror)
{
uint16_t s = cache[texslot & 0x7].s << 5;
uint16_t t = cache[texslot & 0x7].t << 5;

uint32_t width = cache[texslot & 0x7].width;
uint32_t height = cache[texslot & 0x7].height;

/* Cant display < 0, so must clip size and move S,T coord accordingly */
if( tx < 0 )
{
if ( tx < -width * x_scale) { return; }
s += (int)(((double)((-tx) << 5)) * (1.0 / x_scale));
tx = 0;
}

if( ty < 0 )
{
if ( ty < -height * y_scale ) { return; }
t += (int)(((double)((-ty) << 5)) * (1.0 / y_scale));
ty = 0;
}

// mirror horizontally or vertically
if (mirror != MIRROR_DISABLED)
{
if (mirror == MIRROR_X || mirror == MIRROR_XY)
s += ( (width+1) + ((cache[texslot & 0x7].real_width-(width+1))<<1) ) << 5;

if (mirror == MIRROR_Y || mirror == MIRROR_XY)
t += ( (height+1) + ((cache[texslot & 0x7].real_height-(height+1))<<1) ) << 5;
}

/* Calculate the scaling constants based on a 6.10 fixed point system */
int xs = (int)((1.0 / x_scale) * 4096.0);
int ys = (int)((1.0 / y_scale) * 1024.0);
Expand Down Expand Up @@ -652,11 +674,13 @@ void rdp_draw_textured_rectangle_scaled( uint32_t texslot, int tx, int ty, int b
* The pixel X location of the bottom right of the rectangle
* @param[in] by
* The pixel Y location of the bottom right of the rectangle
* @param[in] mirror
* Whether the texture should be mirrored
*/
void rdp_draw_textured_rectangle( uint32_t texslot, int tx, int ty, int bx, int by )
void rdp_draw_textured_rectangle( uint32_t texslot, int tx, int ty, int bx, int by, mirror_t mirror )
{
/* Simple wrapper */
rdp_draw_textured_rectangle_scaled( texslot, tx, ty, bx, by, 1.0, 1.0 );
rdp_draw_textured_rectangle_scaled( texslot, tx, ty, bx, by, 1.0, 1.0, mirror );
}

/**
Expand All @@ -673,11 +697,13 @@ void rdp_draw_textured_rectangle( uint32_t texslot, int tx, int ty, int bx, int
* The pixel X location of the top left of the sprite
* @param[in] y
* The pixel Y location of the top left of the sprite
* @param[in] mirror
* Whether the texture should be mirrored
*/
void rdp_draw_sprite( uint32_t texslot, int x, int y )
void rdp_draw_sprite( uint32_t texslot, int x, int y, mirror_t mirror )
{
/* Just draw a rectangle the size of the sprite */
rdp_draw_textured_rectangle_scaled( texslot, x, y, x + cache[texslot & 0x7].width, y + cache[texslot & 0x7].height, 1.0, 1.0 );
rdp_draw_textured_rectangle_scaled( texslot, x, y, x + cache[texslot & 0x7].width, y + cache[texslot & 0x7].height, 1.0, 1.0, mirror );
}

/**
Expand All @@ -698,15 +724,17 @@ void rdp_draw_sprite( uint32_t texslot, int x, int y )
* Horizontal scaling factor
* @param[in] y_scale
* Vertical scaling factor
* @param[in] mirror
* Whether the texture should be mirrored
*/
void rdp_draw_sprite_scaled( uint32_t texslot, int x, int y, double x_scale, double y_scale )
void rdp_draw_sprite_scaled( uint32_t texslot, int x, int y, double x_scale, double y_scale, mirror_t mirror )
{
/* Since we want to still view the whole sprite, we must resize the rectangle area too */
int new_width = (int)(((double)cache[texslot & 0x7].width * x_scale) + 0.5);
int new_height = (int)(((double)cache[texslot & 0x7].height * y_scale) + 0.5);

/* Draw a rectangle the size of the new sprite */
rdp_draw_textured_rectangle_scaled( texslot, x, y, x + new_width, y + new_height, x_scale, y_scale );
rdp_draw_textured_rectangle_scaled( texslot, x, y, x + new_width, y + new_height, x_scale, y_scale, mirror );
}

/**
Expand Down

4 comments on commit 00a6cc8

@anacierdem
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vieux
Copy link
Contributor Author

@vieux vieux commented on 00a6cc8 Oct 27, 2019 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anacierdem
Copy link
Collaborator

@anacierdem anacierdem commented on 00a6cc8 Oct 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually there are :) But the CI is running on my fork for now. We will see what happens when we enable them on the upstream repo too.

@anacierdem
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opened #71

Please sign in to comment.