mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
render-cg: replace dimage and dsubimage with new renderer
This commit is contained in:
parent
7a3604ccbb
commit
a4df076214
7 changed files with 10 additions and 491 deletions
|
@ -158,8 +158,6 @@ set(SOURCES_CG
|
||||||
# R61524 driver
|
# R61524 driver
|
||||||
src/r61524/r61524.c
|
src/r61524/r61524.c
|
||||||
# Rendering
|
# Rendering
|
||||||
src/render-cg/bopti-asm.s
|
|
||||||
src/render-cg/bopti.c
|
|
||||||
src/render-cg/dclear.c
|
src/render-cg/dclear.c
|
||||||
src/render-cg/dpixel.c
|
src/render-cg/dpixel.c
|
||||||
src/render-cg/drect.c
|
src/render-cg/drect.c
|
||||||
|
|
2
TODO
2
TODO
|
@ -1,8 +1,6 @@
|
||||||
gint 2.8 image things:
|
gint 2.8 image things:
|
||||||
* Margins around the VRAM, and around XYRAM fragments
|
|
||||||
* Design the new image formats, inspired from libimg
|
* Design the new image formats, inspired from libimg
|
||||||
* Replace the [profile] attribute with [format]
|
* Replace the [profile] attribute with [format]
|
||||||
* Single VRAM
|
|
||||||
|
|
||||||
Extensions on existing code:
|
Extensions on existing code:
|
||||||
* usb: add PC->calc reading, and interrupt pipes
|
* usb: add PC->calc reading, and interrupt pipes
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
//---
|
|
||||||
// gint:render-cg:bopti-asm - Assembler drawing routines for bopti
|
|
||||||
//---
|
|
||||||
|
|
||||||
#ifndef GINT_RENDERCG_BOPTIASM
|
|
||||||
#define GINT_RENDERCG_BOPTIASM
|
|
||||||
|
|
||||||
/* bopti_r5g6b5(): Full opaque 16-bit rendering
|
|
||||||
@data Input data (2-aligned)
|
|
||||||
@target Target in VRAM (2-aligned)
|
|
||||||
@width Width of rendered image
|
|
||||||
@height Height of rendered image
|
|
||||||
@in_stride Bytes to ignore between two rows of @data
|
|
||||||
@out_stride Bytes to ignore between two rows of @target */
|
|
||||||
void bopti_r5g6b5(uint16_t const *data, uint16_t *target, int width,
|
|
||||||
int height, int in_stride, int out_stride);
|
|
||||||
|
|
||||||
/* bopti_r5g6b5a(): 16-bit rendering with alpha
|
|
||||||
@data @target @width @height @in_stride @out_stride
|
|
||||||
As in bopti_r5g6b5().
|
|
||||||
@alpha Color code that encodes transparency */
|
|
||||||
void bopti_r5g6b5a(uint16_t const *data, uint16_t *target, int width,
|
|
||||||
int height, int in_stride, int out_stride, uint16_t alpha);
|
|
||||||
|
|
||||||
/* bopti_p8(): 8-bit palette rendering with alpha
|
|
||||||
@data @target @width @height @in_stride @out_stride
|
|
||||||
As in bopti_r5g6b5().
|
|
||||||
@palette Pointer to image palette (256 colors)
|
|
||||||
@alpha Palette index for transparency, if >= 256 no alpha is used */
|
|
||||||
void bopti_p8(uint8_t const *data, uint16_t *target, int width, int height,
|
|
||||||
int in_stride, int out_stride, uint16_t const *palette, int alpha);
|
|
||||||
|
|
||||||
/* bopti_p4(): 4-bit palette rendering with alpha
|
|
||||||
@data @target @width @height @in_stride @out_stride
|
|
||||||
As in bopti_r5g6b5().
|
|
||||||
@palette Pointer to image palette (16 colors)
|
|
||||||
@alpha Palette index for transparency, if >= 16 no alpha is used
|
|
||||||
@offset Initial offset within [data], in number of pixels */
|
|
||||||
void bopti_p4(uint8_t const *data, uint16_t *target, int width, int height,
|
|
||||||
int in_stride, int out_stride, uint16_t const *palette, int alpha,
|
|
||||||
int offset);
|
|
||||||
|
|
||||||
/* bopti_render_clip(): Render with clipping
|
|
||||||
Same parameters as dsubimage(), except for flags. */
|
|
||||||
void bopti_render_clip(int x, int y, bopti_image_t const *img, int left,
|
|
||||||
int top, int width, int height);
|
|
||||||
|
|
||||||
/* bopti_render_clip(): Render without clipping
|
|
||||||
Behaviour is not defined if (left,top)+(width,height) is not included in the
|
|
||||||
source image or (x,y)+(width,height) is not included in the VRAM area.
|
|
||||||
Same parameters as dsubimage(), except for flags. */
|
|
||||||
void bopti_render_noclip(int x, int y, bopti_image_t const *img, int left,
|
|
||||||
int top, int width, int height);
|
|
||||||
|
|
||||||
#endif /* GINT_RENDERCG_BOPTIASM */
|
|
|
@ -1,315 +0,0 @@
|
||||||
|
|
||||||
.global _bopti_r5g6b5
|
|
||||||
.global _bopti_r5g6b5a
|
|
||||||
.global _bopti_p8
|
|
||||||
.global _bopti_p4
|
|
||||||
|
|
||||||
# REGISTER ALLOCATION:
|
|
||||||
# r0: (tmp)
|
|
||||||
# r1: (tmp)
|
|
||||||
# r2: width - 1
|
|
||||||
# r3: target & 2
|
|
||||||
# ---
|
|
||||||
# r4: data
|
|
||||||
# r5: target
|
|
||||||
# r6: width; then, the number of longword operations
|
|
||||||
# r7: height
|
|
||||||
# ---
|
|
||||||
# r8: in_stride
|
|
||||||
# r9: out_stride
|
|
||||||
# r10: x counter
|
|
||||||
# ---
|
|
||||||
# @12: in_stride
|
|
||||||
# @16: out_stride
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
_bopti_r5g6b5:
|
|
||||||
# Target alignment, either 0 (4-aligned) or 2 (2-aligned)
|
|
||||||
mov.l r8, @-r15
|
|
||||||
mov r5, r3
|
|
||||||
mov.l r9, @-r15
|
|
||||||
mov #2, r0
|
|
||||||
mov.l r10, @-r15
|
|
||||||
and r0, r3
|
|
||||||
|
|
||||||
# width-1, used to copy the last longword
|
|
||||||
mov r6, r2
|
|
||||||
add #-1, r2
|
|
||||||
shll r2
|
|
||||||
|
|
||||||
# Input and output strides. Add ending alignment because there is no
|
|
||||||
# corresponding increment in the y-loop.
|
|
||||||
mov.l @(12, r15), r8
|
|
||||||
mov.l @(16, r15), r9
|
|
||||||
mov r5, r0
|
|
||||||
shll r6
|
|
||||||
add r6 ,r0
|
|
||||||
and #2, r0
|
|
||||||
add r0, r8
|
|
||||||
add r0, r9
|
|
||||||
|
|
||||||
# Number of longword operations per row
|
|
||||||
sub r3, r6
|
|
||||||
shlr2 r6
|
|
||||||
|
|
||||||
.r5g6b5_y:
|
|
||||||
# First longword
|
|
||||||
mov.w @r4, r1
|
|
||||||
mov r2, r0
|
|
||||||
mov.w r1, @r5
|
|
||||||
|
|
||||||
# Last longword; align to 4-byte boundaries for target
|
|
||||||
mov.w @(r0, r4), r1
|
|
||||||
add r3, r4
|
|
||||||
mov.w r1, @(r0, r5)
|
|
||||||
add r3, r5
|
|
||||||
|
|
||||||
mov r6, r10
|
|
||||||
tst r6, r6
|
|
||||||
bt .r5g6b5_y_end
|
|
||||||
|
|
||||||
.r5g6b5_x:
|
|
||||||
# Copy longwords
|
|
||||||
movua.l @r4+, r0
|
|
||||||
mov.l r0, @r5
|
|
||||||
|
|
||||||
dt r10
|
|
||||||
bf.s .r5g6b5_x
|
|
||||||
add #4, r5
|
|
||||||
|
|
||||||
.r5g6b5_y_end:
|
|
||||||
|
|
||||||
add r8, r4
|
|
||||||
dt r7
|
|
||||||
bf.s .r5g6b5_y
|
|
||||||
add r9, r5
|
|
||||||
|
|
||||||
# -
|
|
||||||
|
|
||||||
mov.l @r15+, r10
|
|
||||||
mov.l @r15+, r9
|
|
||||||
rts
|
|
||||||
mov.l @r15+, r8
|
|
||||||
|
|
||||||
# REGISTER ALLOCATION:
|
|
||||||
# r0: (tmp)
|
|
||||||
# r1: in_stride
|
|
||||||
# r2: out_stride
|
|
||||||
# r3: x counter
|
|
||||||
# ---
|
|
||||||
# r4: data
|
|
||||||
# r5: target
|
|
||||||
# r6: width
|
|
||||||
# r7: height
|
|
||||||
# ---
|
|
||||||
# r8: alpha
|
|
||||||
# ---
|
|
||||||
# @4: in_stride
|
|
||||||
# @8: out_stride
|
|
||||||
# @12: alpha
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
_bopti_r5g6b5a:
|
|
||||||
# Load alpha value
|
|
||||||
mov.l r8, @-r15
|
|
||||||
mov.l @(12, r15), r8
|
|
||||||
|
|
||||||
# Load input and output strides
|
|
||||||
mov.l @(4, r15), r1
|
|
||||||
mov.l @(8, r15), r2
|
|
||||||
|
|
||||||
.r5g6b5a_y:
|
|
||||||
mov r6, r3
|
|
||||||
|
|
||||||
.r5g6b5a_x:
|
|
||||||
mov.w @r4+, r0
|
|
||||||
cmp/eq r0, r8
|
|
||||||
bt .r5g6b5a_alpha
|
|
||||||
|
|
||||||
mov.w r0, @r5
|
|
||||||
|
|
||||||
.r5g6b5a_alpha:
|
|
||||||
dt r3
|
|
||||||
bf.s .r5g6b5a_x
|
|
||||||
add #2, r5
|
|
||||||
|
|
||||||
# -
|
|
||||||
|
|
||||||
add r1, r4
|
|
||||||
dt r7
|
|
||||||
bf.s .r5g6b5a_y
|
|
||||||
add r2, r5
|
|
||||||
|
|
||||||
# -
|
|
||||||
|
|
||||||
rts
|
|
||||||
mov.l @r15+, r8
|
|
||||||
|
|
||||||
# REGISTER ALLOCATION:
|
|
||||||
# r0: (tmp)
|
|
||||||
# r1: in_stride
|
|
||||||
# r2: out_stride
|
|
||||||
# r3: x counter
|
|
||||||
# ---
|
|
||||||
# r4: data
|
|
||||||
# r5: target
|
|
||||||
# r6: width
|
|
||||||
# r7: height
|
|
||||||
# ---
|
|
||||||
# r8: palette
|
|
||||||
# r9: alpha
|
|
||||||
# ---
|
|
||||||
# @8: in_stride
|
|
||||||
# @12: out_stride
|
|
||||||
# @16: palette
|
|
||||||
# @20: alpha
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
_bopti_p8:
|
|
||||||
# Load palette and in/out strides
|
|
||||||
mov.l r8, @-r15
|
|
||||||
mov.l r9, @-r15
|
|
||||||
mov.l @(16, r15), r8
|
|
||||||
mov.l @(8, r15), r1
|
|
||||||
mov.l @(12, r15), r2
|
|
||||||
|
|
||||||
# Load alpha value
|
|
||||||
mov.l @(20, r15), r9
|
|
||||||
|
|
||||||
.p8_y:
|
|
||||||
mov r6, r3
|
|
||||||
|
|
||||||
.p8_x:
|
|
||||||
mov.b @r4+, r0
|
|
||||||
extu.b r0, r0
|
|
||||||
cmp/eq r0, r9
|
|
||||||
bt .p8_alpha
|
|
||||||
|
|
||||||
# Pass pixel through palette
|
|
||||||
shll r0
|
|
||||||
mov.w @(r0, r8), r0
|
|
||||||
mov.w r0, @r5
|
|
||||||
|
|
||||||
.p8_alpha:
|
|
||||||
dt r3
|
|
||||||
bf.s .p8_x
|
|
||||||
add #2, r5
|
|
||||||
|
|
||||||
# -
|
|
||||||
|
|
||||||
add r1, r4
|
|
||||||
dt r7
|
|
||||||
bf.s .p8_y
|
|
||||||
add r2, r5
|
|
||||||
|
|
||||||
# -
|
|
||||||
|
|
||||||
mov.l @r15+, r9
|
|
||||||
rts
|
|
||||||
mov.l @r15+, r8
|
|
||||||
|
|
||||||
# REGISTER ALLOCATION:
|
|
||||||
# r0: (tmp)
|
|
||||||
# r1: in_stride (in pixels)
|
|
||||||
# r2: out_stride
|
|
||||||
# r3: x counter
|
|
||||||
# ---
|
|
||||||
# r4: data
|
|
||||||
# r5: target
|
|
||||||
# r6: width
|
|
||||||
# r7: height
|
|
||||||
# ---
|
|
||||||
# r8: palette
|
|
||||||
# r9: number of pixels of offset into data (r4)
|
|
||||||
# r10: alpha
|
|
||||||
# ---
|
|
||||||
# @12: in_stride
|
|
||||||
# @16: out_stride
|
|
||||||
# @20: palette
|
|
||||||
# @24: alpha
|
|
||||||
# @28: initial offset (in pixels)
|
|
||||||
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
_bopti_p4:
|
|
||||||
mov.l r8, @-r15
|
|
||||||
mov.l r9, @-r15
|
|
||||||
mov.l r10, @-r15
|
|
||||||
|
|
||||||
# Load palette and in/out strides
|
|
||||||
mov.l @(20, r15), r8
|
|
||||||
mov.l @(12, r15), r1
|
|
||||||
mov.l @(16, r15), r2
|
|
||||||
|
|
||||||
# Load initial offset
|
|
||||||
mov.l @(28, r15), r9
|
|
||||||
|
|
||||||
# Load alpha value
|
|
||||||
mov.l @(24, r15), r10
|
|
||||||
shll r10
|
|
||||||
|
|
||||||
.p4_y:
|
|
||||||
mov r6, r3
|
|
||||||
|
|
||||||
.p4_x:
|
|
||||||
|
|
||||||
# Load 4 bits from offset r9 (in pixels) within image data (r4). Note
|
|
||||||
# that [shlr] puts bit 0 of the shifted register in T.
|
|
||||||
mov r9, r0
|
|
||||||
add #1, r9
|
|
||||||
shlr r0
|
|
||||||
bt.s .p4_x_unaligned
|
|
||||||
mov.b @(r0, r4), r0
|
|
||||||
|
|
||||||
.p4_x_aligned:
|
|
||||||
|
|
||||||
# Load 4 bits from the higher half of @r4 and use them to index the
|
|
||||||
# palette. Since the palette has two-byte entries, we need the color
|
|
||||||
# bits to be in position 000xxxx0.
|
|
||||||
shlr2 r0
|
|
||||||
shlr r0
|
|
||||||
and #0x1e, r0
|
|
||||||
|
|
||||||
cmp/eq r0, r10
|
|
||||||
bt .p4_alpha
|
|
||||||
|
|
||||||
# Pass pixel through palette
|
|
||||||
mov.w @(r0, r8), r0
|
|
||||||
bra .p4_alpha
|
|
||||||
mov.w r0, @r5
|
|
||||||
|
|
||||||
.p4_x_unaligned:
|
|
||||||
|
|
||||||
# Load 4 bits from the lower half of @r4 into position 000xxxx0.
|
|
||||||
shll r0
|
|
||||||
and #0x1e, r0
|
|
||||||
|
|
||||||
cmp/eq r0, r10
|
|
||||||
bt .p4_alpha
|
|
||||||
|
|
||||||
# Pass pixel through palette
|
|
||||||
mov.w @(r0, r8), r0
|
|
||||||
mov.w r0, @r5
|
|
||||||
|
|
||||||
.p4_alpha:
|
|
||||||
|
|
||||||
dt r3
|
|
||||||
bf.s .p4_x
|
|
||||||
add #2, r5
|
|
||||||
|
|
||||||
.p4_y_end:
|
|
||||||
|
|
||||||
add r1, r9
|
|
||||||
dt r7
|
|
||||||
bf.s .p4_y
|
|
||||||
add r2, r5
|
|
||||||
|
|
||||||
# -
|
|
||||||
|
|
||||||
mov.l @r15+, r10
|
|
||||||
mov.l @r15+, r9
|
|
||||||
rts
|
|
||||||
mov.l @r15+, r8
|
|
|
@ -1,105 +0,0 @@
|
||||||
#include <gint/defs/types.h>
|
|
||||||
#include <gint/display.h>
|
|
||||||
#include "bopti-asm.h"
|
|
||||||
|
|
||||||
struct box {
|
|
||||||
/* Target location of top-left corner */
|
|
||||||
int x, y;
|
|
||||||
/* Width and height of rendered sub-image */
|
|
||||||
int w, h;
|
|
||||||
/* Source bounding box (low included, high excluded) */
|
|
||||||
int left, top;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PX_R5G6B5 = 0,
|
|
||||||
PX_R5G6B5A = 1,
|
|
||||||
PX_P8 = 2,
|
|
||||||
PX_P4 = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
void bopti_render(bopti_image_t const *img, struct box *box)
|
|
||||||
{
|
|
||||||
/* Offset in video RAM and output stride */
|
|
||||||
uint16_t *target = gint_vram + (396 * box->y + box->x);
|
|
||||||
int out = 2 * (396 - box->w);
|
|
||||||
|
|
||||||
int profile = img->profile;
|
|
||||||
void const *data = img->data;
|
|
||||||
|
|
||||||
int w = box->w;
|
|
||||||
int h = box->h;
|
|
||||||
|
|
||||||
if(profile == PX_R5G6B5 || profile == PX_R5G6B5A)
|
|
||||||
{
|
|
||||||
/* Input stride */
|
|
||||||
int true_width = img->width + (img->width & 1);
|
|
||||||
int in = 2 * (true_width - w);
|
|
||||||
|
|
||||||
data += 2 * (true_width * box->top + box->left);
|
|
||||||
|
|
||||||
if(profile == PX_R5G6B5)
|
|
||||||
bopti_r5g6b5(data, target, w, h, in, out);
|
|
||||||
else
|
|
||||||
bopti_r5g6b5a(data, target, w, h, in, out, img->alpha);
|
|
||||||
}
|
|
||||||
else if(profile == PX_P8)
|
|
||||||
{
|
|
||||||
/* Palette has 0x100 entries of 2 bytes each */
|
|
||||||
uint16_t const *palette = data;
|
|
||||||
data += 512;
|
|
||||||
|
|
||||||
int in = img->width - w;
|
|
||||||
data += img->width * box->top + box->left;
|
|
||||||
|
|
||||||
bopti_p8(data, target, w, h, in, out, palette, img->alpha);
|
|
||||||
}
|
|
||||||
else if(profile == PX_P4)
|
|
||||||
{
|
|
||||||
/* Palette has 0x10 entries of 2 bytes each */
|
|
||||||
uint16_t const *palette = data;
|
|
||||||
data += 32;
|
|
||||||
|
|
||||||
int true_width = img->width + (img->width & 1);
|
|
||||||
|
|
||||||
/* Due to nibble alignment being a hassle, in this function the
|
|
||||||
input stride is expressed in pixels. */
|
|
||||||
int in = true_width - w;
|
|
||||||
/* Also we don't move pointers, we just use pixel offsets. */
|
|
||||||
int offset = true_width * box->top + box->left;
|
|
||||||
|
|
||||||
bopti_p4(data, target, w, h, in, out, palette, img->alpha,
|
|
||||||
offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bopti_render_clip(int x, int y, bopti_image_t const *img, int left,
|
|
||||||
int top, int width, int height)
|
|
||||||
{
|
|
||||||
/* Adjust the bounding box of the input image */
|
|
||||||
if(left < 0) width += left, x -= left, left = 0;
|
|
||||||
if(top < 0) height += top, y -= top, top = 0;
|
|
||||||
if(left + width > img->width) width = img->width - left;
|
|
||||||
if(top + height > img->height) height = img->height - top;
|
|
||||||
|
|
||||||
/* Check whether the box intersects the screen */
|
|
||||||
if(width <= 0 || height <= 0) return;
|
|
||||||
if(x + width <= 0 || x >= 396 || y + height <= 0 || y >= 224) return;
|
|
||||||
|
|
||||||
/* Intersect with the bounding box on-screen */
|
|
||||||
if(y < 0) top -= y, height += y, y = 0;
|
|
||||||
if(y + height > 224) height = (224 - y);
|
|
||||||
if(x < 0) left -= x, width += x, x = 0;
|
|
||||||
if(x + width > 396) width = (396 - x);
|
|
||||||
|
|
||||||
/* Finish with the renderer */
|
|
||||||
struct box box = { x, y, width, height, left, top };
|
|
||||||
bopti_render(img, &box);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bopti_render_noclip(int x, int y, bopti_image_t const *img, int left,
|
|
||||||
int top, int width, int height)
|
|
||||||
{
|
|
||||||
struct box box = { x, y, width, height, left, top };
|
|
||||||
bopti_render(img, &box);
|
|
||||||
}
|
|
|
@ -1,16 +1,14 @@
|
||||||
#include <gint/display.h>
|
#include <gint/display.h>
|
||||||
#include "bopti-asm.h"
|
|
||||||
|
|
||||||
/* dsubimage(): Render a section of an image */
|
/* dsubimage(): Render a section of an image */
|
||||||
void dsubimage(int x, int y, bopti_image_t const *img, int left, int top,
|
void dsubimage(int x, int y, image_t const *img, int left, int top,
|
||||||
int width, int height, int flags)
|
int w, int h, int flags)
|
||||||
{
|
{
|
||||||
if(flags & DIMAGE_NOCLIP)
|
int p = img->profile;
|
||||||
{
|
if(p == IMAGE_RGB565 || p == IMAGE_RGB565A)
|
||||||
bopti_render_noclip(x, y, img, left, top, width, height);
|
return dsubimage_rgb16(x, y, img, left, top, w, h, flags);
|
||||||
}
|
if(p == IMAGE_P8_RGB565 || p == IMAGE_P8_RGB565A)
|
||||||
else
|
return dsubimage_p8(x, y, img, left, top, w, h, flags);
|
||||||
{
|
if(p == IMAGE_P4_RGB565 || p == IMAGE_P4_RGB565A)
|
||||||
bopti_render_clip(x, y, img, left, top, width, height);
|
return dsubimage_p4(x, y, img, left, top, w, h, flags);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ bool gint_image_clip_input(image_t const *img, struct gint_image_box *b,
|
||||||
return false;
|
return false;
|
||||||
if(b->x + b->w <= 0 || b->x >= out_w)
|
if(b->x + b->w <= 0 || b->x >= out_w)
|
||||||
return false;
|
return false;
|
||||||
if(b->y + b->w <= 0 || b->y >= out_h)
|
if(b->y + b->h <= 0 || b->y >= out_h)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue