Merge pull request #2 from yawut/wiiu-noframebuffer

render: Avoid using framebuffer, other tweaks
This commit is contained in:
rw-r-r-0644
2019-03-18 15:21:26 +01:00
committed by GitHub
8 changed files with 828 additions and 479 deletions

View File

@@ -37,6 +37,7 @@
#include <gx2/clear.h>
#include <gx2/mem.h>
#include <gx2/event.h>
#include <gx2r/surface.h>
#include <gx2r/buffer.h>
#include <gx2r/draw.h>
@@ -53,44 +54,76 @@ int WIIU_SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata;
float *a_position = WIIU_AllocRenderData(data, sizeof(float) * 8);
float *a_texCoord = WIIU_AllocRenderData(data, sizeof(float) * 8);
float *u_mod = WIIU_AllocRenderData(data, sizeof(float) * 4);
GX2RBuffer *a_position, *a_texCoord;
WIIUVec2 *a_position_vals, *a_texCoord_vals;
float x_min, y_min, x_max, y_max;
if (texture->access & SDL_TEXTUREACCESS_TARGET) {
GX2RInvalidateSurface(&tdata->texture.surface, 0, 0);
}
/* Update texture rendering state */
WIIU_TextureStartRendering(data, tdata);
/* Allocate attribute buffers */
a_position = WIIU_AllocRenderData(data, (GX2RBuffer) {
.flags =
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_WRITE,
.elemSize = sizeof(WIIUVec2), // float x/y for each corner
.elemCount = 4, // 4 corners
});
a_texCoord = WIIU_AllocRenderData(data, (GX2RBuffer) {
.flags =
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_WRITE,
.elemSize = sizeof(WIIUVec2),
.elemCount = 4, // 4 corners
});
/* Compute vertex points */
float x_min = renderer->viewport.x + dstrect->x;
float y_min = renderer->viewport.y + dstrect->y;
float x_max = renderer->viewport.x + dstrect->x + dstrect->w;
float y_max = renderer->viewport.y + dstrect->y + dstrect->h;
a_position[0] = x_min; a_position[1] = y_min;
a_position[2] = x_max; a_position[3] = y_min;
a_position[4] = x_max; a_position[5] = y_max;
a_position[6] = x_min; a_position[7] = y_max;
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, a_position, sizeof(float) * 8);
x_min = renderer->viewport.x + dstrect->x;
y_min = renderer->viewport.y + dstrect->y;
x_max = renderer->viewport.x + dstrect->x + dstrect->w;
y_max = renderer->viewport.y + dstrect->y + dstrect->h;
/* Save them */
a_position_vals = GX2RLockBufferEx(a_position, 0);
a_position_vals[0] = (WIIUVec2){.x = x_min, .y = y_min};
a_position_vals[1] = (WIIUVec2){.x = x_max, .y = y_min};
a_position_vals[2] = (WIIUVec2){.x = x_max, .y = y_max};
a_position_vals[3] = (WIIUVec2){.x = x_min, .y = y_max};
GX2RUnlockBufferEx(a_position, 0);
/* Compute texture coords */
a_texCoord[0] = srcrect->x; a_texCoord[1] = srcrect->y + srcrect->h;
a_texCoord[2] = srcrect->x + srcrect->w; a_texCoord[3] = srcrect->y + srcrect->h;
a_texCoord[4] = srcrect->x + srcrect->w; a_texCoord[5] = srcrect->y;
a_texCoord[6] = srcrect->x; a_texCoord[7] = srcrect->y;
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, a_texCoord, sizeof(float) * 8);
/* Compute color/alpha mod */
u_mod[0] = (float)texture->r / 255.0f;
u_mod[1] = (float)texture->g / 255.0f;
u_mod[2] = (float)texture->b / 255.0f;
u_mod[3] = (float)texture->a / 255.0f;
a_texCoord_vals = GX2RLockBufferEx(a_texCoord, 0);
a_texCoord_vals[0] = (WIIUVec2) {
.x = srcrect->x,
.y = srcrect->y + srcrect->h,
};
a_texCoord_vals[1] = (WIIUVec2) {
.x = srcrect->x + srcrect->w,
.y = srcrect->y + srcrect->h,
};
a_texCoord_vals[2] = (WIIUVec2) {
.x = srcrect->x + srcrect->w,
.y = srcrect->y,
};
a_texCoord_vals[3] = (WIIUVec2) {
.x = srcrect->x,
.y = srcrect->y,
};
GX2RUnlockBufferEx(a_texCoord, 0);
/* Render */
GX2SetContextState(data->ctx);
wiiuSetTextureShader();
GX2SetPixelTexture(&tdata->texture, 0);
GX2SetPixelSampler(&tdata->sampler, 0);
GX2SetAttribBuffer(0, sizeof(float) * 8, sizeof(float) * 2, a_position);
GX2SetAttribBuffer(1, sizeof(float) * 8, sizeof(float) * 2, a_texCoord);
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)data->u_viewSize);
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[1].offset, 4, (uint32_t *)tdata->u_texSize);
GX2SetPixelUniformReg(wiiuTextureShader.pixelShader->uniformVars[0].offset, 4, (uint32_t*)u_mod);
GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0);
GX2RSetAttributeBuffer(a_texCoord, 1, a_texCoord->elemSize, 0);
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&data->u_viewSize);
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[1].offset, 4, (uint32_t *)&tdata->u_texSize);
GX2SetPixelUniformReg(wiiuTextureShader.pixelShader->uniformVars[0].offset, 4, (uint32_t *)&tdata->u_mod);
WIIU_SDL_SetGX2BlendMode(texture->blendMode);
GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1);
@@ -104,9 +137,8 @@ int WIIU_SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata;
float *a_position = WIIU_AllocRenderData(data, sizeof(float) * 8);
float *a_texCoord = WIIU_AllocRenderData(data, sizeof(float) * 8);
float *u_mod = WIIU_AllocRenderData(data, sizeof(float) * 4);
GX2RBuffer *a_position, *a_texCoord;
WIIUVec2 *a_position_vals, *a_texCoord_vals;
/* Compute real vertex points */
float x_min = renderer->viewport.x + dstrect->x;
@@ -116,41 +148,87 @@ int WIIU_SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
float cx = x_min + center->x;
float cy = y_min + center->y;
double r = angle * (M_PI / 180.0);
float rvb[8] = {
(flip & SDL_FLIP_HORIZONTAL) ? x_max : x_min, (flip & SDL_FLIP_VERTICAL) ? y_max : y_min,
(flip & SDL_FLIP_HORIZONTAL) ? x_min : x_max, (flip & SDL_FLIP_VERTICAL) ? y_max : y_min,
(flip & SDL_FLIP_HORIZONTAL) ? x_min : x_max, (flip & SDL_FLIP_VERTICAL) ? y_min : y_max,
(flip & SDL_FLIP_HORIZONTAL) ? x_max : x_min, (flip & SDL_FLIP_VERTICAL) ? y_min : y_max,
WIIUVec2 rvb[4] = {
{
.x = (flip & SDL_FLIP_HORIZONTAL) ? x_max : x_min,
.y = (flip & SDL_FLIP_VERTICAL) ? y_max : y_min,
},
{
.x = (flip & SDL_FLIP_HORIZONTAL) ? x_min : x_max,
.y = (flip & SDL_FLIP_VERTICAL) ? y_max : y_min,
},
{
.x = (flip & SDL_FLIP_HORIZONTAL) ? x_min : x_max,
.y = (flip & SDL_FLIP_VERTICAL) ? y_min : y_max,
},
{
.x = (flip & SDL_FLIP_HORIZONTAL) ? x_max : x_min,
.y = (flip & SDL_FLIP_VERTICAL) ? y_min : y_max,
},
};
for (int i = 0; i < 8; i += 2) {
a_position[i+0] = cx + (SDL_cos(r) * (rvb[i+0] - cx) - SDL_sin(r) * (rvb[i+1] - cy));
a_position[i+1] = cy + (SDL_cos(r) * (rvb[i+1] - cy) + SDL_sin(r) * (rvb[i+0] - cx));
if (texture->access & SDL_TEXTUREACCESS_TARGET) {
GX2RInvalidateSurface(&tdata->texture.surface, 0, 0);
}
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, a_position, sizeof(float) * 8);
/* Update texture rendering state */
WIIU_TextureStartRendering(data, tdata);
/* Allocate attribute buffers */
a_position = WIIU_AllocRenderData(data, (GX2RBuffer) {
.flags =
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_WRITE,
.elemSize = sizeof(WIIUVec2), // float x/y for each corner
.elemCount = 4, // 4 corners
});
a_texCoord = WIIU_AllocRenderData(data, (GX2RBuffer) {
.flags =
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_WRITE,
.elemSize = sizeof(WIIUVec2), // float x/y for each corner
.elemCount = 4, // 4 corners
});
/* Save vertex points */
a_position_vals = GX2RLockBufferEx(a_position, 0);
for (int i = 0; i < 4; i++) {
a_position_vals[i] = (WIIUVec2) {
.x = cx + (SDL_cos(r) * (rvb[i].x - cx) - SDL_sin(r) * (rvb[i].y - cy)),
.y = cy + (SDL_cos(r) * (rvb[i].y - cy) + SDL_sin(r) * (rvb[i].x - cx)),
};
}
GX2RUnlockBufferEx(a_position, 0);
/* Compute texture coords */
a_texCoord[0] = srcrect->x; a_texCoord[1] = srcrect->y + srcrect->h;
a_texCoord[2] = srcrect->x + srcrect->w; a_texCoord[3] = srcrect->y + srcrect->h;
a_texCoord[4] = srcrect->x + srcrect->w; a_texCoord[5] = srcrect->y;
a_texCoord[6] = srcrect->x; a_texCoord[7] = srcrect->y;
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, a_texCoord, sizeof(float) * 8);
/* Compute color/alpha mod */
u_mod[0] = (float)texture->r / 255.0f;
u_mod[1] = (float)texture->g / 255.0f;
u_mod[2] = (float)texture->b / 255.0f;
u_mod[3] = (float)texture->a / 255.0f;
a_texCoord_vals = GX2RLockBufferEx(a_texCoord, 0);
a_texCoord_vals[0] = (WIIUVec2) {
.x = srcrect->x,
.y = srcrect->y + srcrect->h,
};
a_texCoord_vals[1] = (WIIUVec2) {
.x = srcrect->x + srcrect->w,
.y = srcrect->y + srcrect->h,
};
a_texCoord_vals[2] = (WIIUVec2) {
.x = srcrect->x + srcrect->w,
.y = srcrect->y,
};
a_texCoord_vals[3] = (WIIUVec2) {
.x = srcrect->x,
.y = srcrect->y,
};
GX2RUnlockBufferEx(a_texCoord, 0);
/* Render */
GX2SetContextState(data->ctx);
wiiuSetTextureShader();
GX2SetPixelTexture(&tdata->texture, 0);
GX2SetPixelSampler(&tdata->sampler, 0);
GX2SetAttribBuffer(0, sizeof(float) * 8, sizeof(float) * 2, a_position);
GX2SetAttribBuffer(1, sizeof(float) * 8, sizeof(float) * 2, a_texCoord);
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)data->u_viewSize);
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[1].offset, 4, (uint32_t *)tdata->u_texSize);
GX2SetPixelUniformReg(wiiuTextureShader.pixelShader->uniformVars[0].offset, 4, (uint32_t*)u_mod);
GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0);
GX2RSetAttributeBuffer(a_texCoord, 1, a_texCoord->elemSize, 0);
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&data->u_viewSize);
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[1].offset, 4, (uint32_t *)&tdata->u_texSize);
GX2SetPixelUniformReg(wiiuTextureShader.pixelShader->uniformVars[0].offset, 4, (uint32_t *)&tdata->u_mod);
WIIU_SDL_SetGX2BlendMode(texture->blendMode);
GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1);
@@ -161,27 +239,41 @@ int WIIU_SDL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points
int count)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
GX2RBuffer *a_position;
WIIUVec2 *a_position_vals;
/* Compute colors */
float u_color[4] = {(float)renderer->r / 255.0f,
(float)renderer->g / 255.0f,
(float)renderer->b / 255.0f,
(float)renderer->a / 255.0f};
/* Compute colours */
WIIUVec4 u_colour = {
.r = (float)renderer->r / 255.0f,
.g = (float)renderer->g / 255.0f,
.b = (float)renderer->b / 255.0f,
.a = (float)renderer->a / 255.0f,
};
/* Compute vertex pos */
float *a_position = WIIU_AllocRenderData(data, sizeof(float) * 2 * count);
/* Allocate attribute buffers */
a_position = WIIU_AllocRenderData(data, (GX2RBuffer) {
.flags =
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_WRITE,
.elemSize = sizeof(WIIUVec2), /* float x/y for each point */
.elemCount = count,
});
/* Compute vertex positions */
a_position_vals = GX2RLockBufferEx(a_position, 0);
for (int i = 0; i < count; ++i) {
a_position[i*2+0] = (float)renderer->viewport.x + points[i].x;
a_position[i*2+1] = (float)renderer->viewport.y + points[i].y;
a_position_vals[i] = (WIIUVec2) {
.x = (float)renderer->viewport.x + points[i].x,
.y = (float)renderer->viewport.y + points[i].y,
};
}
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, a_position, sizeof(float) * 2 * count);
GX2RUnlockBufferEx(a_position, 0);
/* Render points */
GX2SetContextState(data->ctx);
wiiuSetColorShader();
GX2SetAttribBuffer(0, sizeof(float) * 2 * count, sizeof(float) * 2, a_position);
GX2SetVertexUniformReg(wiiuColorShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)data->u_viewSize);
GX2SetPixelUniformReg(wiiuColorShader.pixelShader->uniformVars[0].offset, 4, (uint32_t*)u_color);
GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0);
GX2SetVertexUniformReg(wiiuColorShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&data->u_viewSize);
GX2SetPixelUniformReg(wiiuColorShader.pixelShader->uniformVars[0].offset, 4, (uint32_t *)&u_colour);
WIIU_SDL_SetGX2BlendMode(renderer->blendMode);
GX2DrawEx(GX2_PRIMITIVE_MODE_POINTS, count, 0, 1);
@@ -193,27 +285,41 @@ int WIIU_SDL_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
int count)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
GX2RBuffer *a_position;
WIIUVec2 *a_position_vals;
/* Compute colors */
float u_color[4] = {(float)renderer->r / 255.0f,
(float)renderer->g / 255.0f,
(float)renderer->b / 255.0f,
(float)renderer->a / 255.0f};
/* Compute colours */
WIIUVec4 u_colour = {
.r = (float)renderer->r / 255.0f,
.g = (float)renderer->g / 255.0f,
.b = (float)renderer->b / 255.0f,
.a = (float)renderer->a / 255.0f,
};
/* Compute vertex pos */
float *a_position = WIIU_AllocRenderData(data, sizeof(float) * 2 * count);
/* Allocate attribute buffers */
a_position = WIIU_AllocRenderData(data, (GX2RBuffer) {
.flags =
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_WRITE,
.elemSize = sizeof(WIIUVec2), /* float x/y for each point */
.elemCount = count,
});
/* Compute vertex positions */
a_position_vals = GX2RLockBufferEx(a_position, 0);
for (int i = 0; i < count; ++i) {
a_position[i*2+0] = (float)renderer->viewport.x + points[i].x;
a_position[i*2+1] = (float)renderer->viewport.y + points[i].y;
a_position_vals[i] = (WIIUVec2) {
.x = (float)renderer->viewport.x + points[i].x,
.y = (float)renderer->viewport.y + points[i].y,
};
}
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, a_position, sizeof(float) * 2 * count);
GX2RUnlockBufferEx(a_position, 0);
/* Render lines */
GX2SetContextState(data->ctx);
wiiuSetColorShader();
GX2SetAttribBuffer(0, sizeof(float) * 2 * count, sizeof(float) * 2, a_position);
GX2SetVertexUniformReg(wiiuColorShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)data->u_viewSize);
GX2SetPixelUniformReg(wiiuColorShader.pixelShader->uniformVars[0].offset, 4, (uint32_t*)u_color);
GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0);
GX2SetVertexUniformReg(wiiuColorShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&data->u_viewSize);
GX2SetPixelUniformReg(wiiuColorShader.pixelShader->uniformVars[0].offset, 4, (uint32_t *)&u_colour);
WIIU_SDL_SetGX2BlendMode(renderer->blendMode);
GX2DrawEx(GX2_PRIMITIVE_MODE_LINE_STRIP, count, 0, 1);
@@ -223,66 +329,78 @@ int WIIU_SDL_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
int WIIU_SDL_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
GX2RBuffer *a_position;
WIIUVec2 *a_position_vals;
/* Compute colors */
float u_color[4] = {(float)renderer->r / 255.0f,
(float)renderer->g / 255.0f,
(float)renderer->b / 255.0f,
(float)renderer->a / 255.0f};
/* Compute colours */
WIIUVec4 u_colour = {
.r = (float)renderer->r / 255.0f,
.g = (float)renderer->g / 255.0f,
.b = (float)renderer->b / 255.0f,
.a = (float)renderer->a / 255.0f,
};
/* Compute vertex pos */
float vx = (float)renderer->viewport.x;
float vy = (float)renderer->viewport.y;
float *a_position = WIIU_AllocRenderData(data, sizeof(float) * 8 * count);
/* Allocate attribute buffers */
a_position = WIIU_AllocRenderData(data, (GX2RBuffer) {
.flags =
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_WRITE,
.elemSize = sizeof(WIIUVec2), // x/y float per corner
.elemCount = 4 * count, // 4 corners per square
});
/* Compute vertex positions */
a_position_vals = GX2RLockBufferEx(a_position, 0);
for (int i = 0; i < count; ++i) {
a_position[i*8+0] = vx + rects[i].x;
a_position[i*8+1] = vy + rects[i].y;
a_position[i*8+2] = vx + rects[i].x + rects[i].w;
a_position[i*8+3] = vy + rects[i].y;
a_position[i*8+4] = vx + rects[i].x + rects[i].w;
a_position[i*8+5] = vy + rects[i].y + rects[i].h;
a_position[i*8+6] = vx + rects[i].x;
a_position[i*8+7] = vy + rects[i].y + rects[i].h;
a_position_vals[i*4 + 0] = (WIIUVec2) {
.x = vx + rects[i].x,
.y = vy + rects[i].y,
};
a_position_vals[i*4 + 1] = (WIIUVec2) {
.x = vx + rects[i].x + rects[i].w,
.y = vy + rects[i].y,
};
a_position_vals[i*4 + 2] = (WIIUVec2) {
.x = vx + rects[i].x + rects[i].w,
.y = vy + rects[i].y + rects[i].h,
};
a_position_vals[i*4 + 3] = (WIIUVec2) {
.x = vx + rects[i].x,
.y = vy + rects[i].y + rects[i].h,
};
}
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, a_position, sizeof(float) * 8 * count);
GX2RUnlockBufferEx(a_position, 0);
/* Render rects */
GX2SetContextState(data->ctx);
wiiuSetColorShader();
GX2SetAttribBuffer(0, sizeof(float) * 8 * count, sizeof(float) * 2, a_position);
GX2SetVertexUniformReg(wiiuColorShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)data->u_viewSize);
GX2SetPixelUniformReg(wiiuColorShader.pixelShader->uniformVars[0].offset, 4, (uint32_t*)u_color);
GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0);
GX2SetVertexUniformReg(wiiuColorShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&data->u_viewSize);
GX2SetPixelUniformReg(wiiuColorShader.pixelShader->uniformVars[0].offset, 4, (uint32_t *)&u_colour);
WIIU_SDL_SetGX2BlendMode(renderer->blendMode);
GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4 * count, 0, 1);
return 0;
}
void WIIU_SDL_RenderPresent(SDL_Renderer * renderer)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
GX2Flush();
GX2DrawDone();
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, data->cbuf.surface.image, data->cbuf.surface.imageSize);
if (window) {
SDL_UpdateWindowSurface(window);
}
WIIU_FreeRenderData(data);
}
int WIIU_SDL_RenderClear(SDL_Renderer * renderer)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
GX2ClearColor(&data->cbuf,
WIIU_RenderData* data = (WIIU_RenderData*) renderer->driverdata;
SDL_Texture* target = WIIU_GetRenderTarget(renderer);
WIIU_TextureData* tdata = (WIIU_TextureData*) target->driverdata;
GX2ClearColor(&tdata->cbuf,
(float)renderer->r / 255.0f,
(float)renderer->g / 255.0f,
(float)renderer->b / 255.0f,
(float)renderer->a / 255.0f);
/* Restore SDL context state */
GX2SetContextState(data->ctx);
return 0;
}
@@ -320,7 +438,7 @@ static void WIIU_SDL_SetGX2BlendMode(SDL_BlendMode mode)
/* A = [srcA * 0] + [dstA * 1] */
GX2_BLEND_MODE_ZERO, GX2_BLEND_MODE_ONE,
GX2_BLEND_COMBINE_MODE_ADD);
}
}
}
#endif //SDL_VIDEO_RENDER_WIIU
#endif /* SDL_VIDEO_RENDER_WIIU */

View File

@@ -1,7 +1,7 @@
/*
Simple DirectMedia Layer
Copyright (C) 2018-2018 Ash Logan <ash@heyquark.com>
Copyright (C) 2018-2018 Roberto Van Eeden <r.r.qwertyuiop.r.r@gmail.com>
Copyright (C) 2018-2019 Ash Logan <ash@heyquark.com>
Copyright (C) 2018-2019 Roberto Van Eeden <r.r.qwertyuiop.r.r@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -26,31 +26,20 @@
#include "../../video/wiiu/SDL_wiiuvideo.h"
#include "../../video/wiiu/wiiu_shaders.h"
#include "../SDL_sysrender.h"
#include "SDL_hints.h"
#include "SDL_render_wiiu.h"
#include <gx2/registers.h>
#include <gx2r/surface.h>
#include <malloc.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
SDL_RenderDriver WIIU_RenderDriver;
SDL_Renderer *WIIU_SDL_CreateRenderer(SDL_Window * window, Uint32 flags)
{
SDL_Surface *surface;
SDL_Renderer *renderer;
WIIU_RenderData *data;
surface = SDL_GetWindowSurface(window);
if (!surface) {
return NULL;
}
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_OutOfMemory();
@@ -64,14 +53,12 @@ SDL_Renderer *WIIU_SDL_CreateRenderer(SDL_Window * window, Uint32 flags)
return NULL;
}
// See sdl_render_wiiu.h for explanations of commented-out functions
/* Setup renderer functions */
renderer->WindowEvent = WIIU_SDL_WindowEvent;
renderer->GetOutputSize = WIIU_SDL_GetOutputSize;
renderer->CreateTexture = WIIU_SDL_CreateTexture;
//renderer->SetTextureColorMod = WIIU_SDL_SetTextureColorMod;
//renderer->SetTextureAlphaMod = WIIU_SDL_SetTextureAlphaMod;
//renderer->SetTextureBlendMode = WIIU_SDL_SetTextureBlendMode;
renderer->SetTextureColorMod = WIIU_SDL_SetTextureColorMod;
renderer->SetTextureAlphaMod = WIIU_SDL_SetTextureAlphaMod;
renderer->UpdateTexture = WIIU_SDL_UpdateTexture;
renderer->LockTexture = WIIU_SDL_LockTexture;
renderer->UnlockTexture = WIIU_SDL_UnlockTexture;
@@ -92,68 +79,83 @@ SDL_Renderer *WIIU_SDL_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->driverdata = data;
renderer->window = window;
// Prepare shaders
/* Prepare shaders */
wiiuInitTextureShader();
wiiuInitColorShader();
// List of attibutes to free after render
/* List of attibutes to free after render */
data->listfree = NULL;
// Setup line and point size
/* Setup line and point size */
GX2SetLineWidth(1.0f);
GX2SetPointSize(1.0f, 1.0f);
// Create a fresh context state
/* Create a fresh context state */
data->ctx = (GX2ContextState *) memalign(GX2_CONTEXT_STATE_ALIGNMENT, sizeof(GX2ContextState));
memset(data->ctx, 0, sizeof(GX2ContextState));
SDL_memset(data->ctx, 0, sizeof(GX2ContextState));
GX2SetupContextStateEx(data->ctx, TRUE);
GX2SetContextState(data->ctx);
// Setup colour buffer, rendering to the window
/* Setup some context state options */
GX2SetAlphaTest(TRUE, GX2_COMPARE_FUNC_GREATER, 0.0f);
GX2SetDepthOnlyControl(FALSE, FALSE, GX2_COMPARE_FUNC_NEVER);
GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, FALSE, FALSE);
/* Make a texture for the window */
WIIU_SDL_CreateWindowTex(renderer, window);
/* Setup colour buffer, rendering to the window */
WIIU_SDL_SetRenderTarget(renderer, NULL);
return renderer;
}
void WIIU_SDL_CreateWindowTex(SDL_Renderer * renderer, SDL_Window * window)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
if (data->windowTex.driverdata) {
WIIU_SDL_DestroyTexture(renderer, &data->windowTex);
data->windowTex = (SDL_Texture) {0};
}
/* Allocate a buffer for the window */
data->windowTex = (SDL_Texture) {
.format = SDL_PIXELFORMAT_RGBA8888,
.r = 255, .g = 255, .b = 255, .a = 255,
};
SDL_GetWindowSize(window, &data->windowTex.w, &data->windowTex.h);
/* Setup texture and color buffer for the window */
WIIU_SDL_CreateTexture(renderer, &data->windowTex);
}
int WIIU_SDL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
GX2Surface *target;
/* Set window or texture as target */
WIIU_TextureData *tdata = (WIIU_TextureData *)((texture) ? texture->driverdata
: data->windowTex.driverdata);
if (texture) {
// Set texture as target
WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata;
target = &tdata->texture.surface;
} else {
// Set window texture as target
WIIU_WindowData *wdata = (WIIU_WindowData *) SDL_GetWindowData(renderer->window, WIIU_WINDOW_DATA);
target = &wdata->texture.surface;
}
/* Wait for the texture rendering to finish */
WIIU_TextureCheckWaitRendering(data, tdata);
// Update color buffer
memset(&data->cbuf, 0, sizeof(data->cbuf));
memcpy(&data->cbuf.surface, target, sizeof(GX2Surface));
data->cbuf.surface.use = GX2_SURFACE_USE_TEXTURE | GX2_SURFACE_USE_COLOR_BUFFER;
data->cbuf.viewNumSlices = 1;
GX2InitColorBufferRegs(&data->cbuf);
/* Update u_viewSize */
data->u_viewSize = (WIIUVec4) {
.x = (float)tdata->cbuf.surface.width,
.y = (float)tdata->cbuf.surface.height,
};
// Update u_viewSize
data->u_viewSize[0] = data->cbuf.surface.width;
data->u_viewSize[1] = data->cbuf.surface.height;
/* Update context state */
GX2SetColorBuffer(&tdata->cbuf, GX2_RENDER_TARGET_0);
// Update context state
GX2SetContextState(data->ctx);
GX2SetColorBuffer(&data->cbuf, GX2_RENDER_TARGET_0);
// These may be unnecessary - see SDL_render.c: SDL_SetRenderTarget's calls
// to UpdateViewport and UpdateClipRect. TODO for once the render is
// basically working.
GX2SetViewport(0, 0, (float)data->cbuf.surface.width, (float)data->cbuf.surface.height, 0.0f, 1.0f);
GX2SetScissor(0, 0, (float)data->cbuf.surface.width, (float)data->cbuf.surface.height);
GX2SetAlphaTest(TRUE, GX2_COMPARE_FUNC_GREATER, 0.0f);
GX2SetDepthOnlyControl(FALSE, FALSE, GX2_COMPARE_FUNC_NEVER);
GX2SetColorControl(GX2_LOGIC_OP_COPY, 0xFF, FALSE, TRUE);
GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, FALSE, FALSE);
/* These may be unnecessary - see SDL_render.c: SDL_SetRenderTarget's calls
to UpdateViewport and UpdateClipRect. TODO for once the render is
basically working */
GX2SetViewport(0, 0, (float)tdata->cbuf.surface.width, (float)tdata->cbuf.surface.height, 0.0f, 1.0f);
GX2SetScissor(0, 0, (float)tdata->cbuf.surface.width, (float)tdata->cbuf.surface.height);
return 0;
}
@@ -162,11 +164,7 @@ void WIIU_SDL_DestroyRenderer(SDL_Renderer * renderer)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
while (data->listfree) {
void *ptr = data->listfree;
data->listfree = data->listfree->next;
SDL_free(ptr);
}
WIIU_FreeRenderData(data);
free(data->ctx);
@@ -180,31 +178,35 @@ void WIIU_SDL_DestroyRenderer(SDL_Renderer * renderer)
int WIIU_SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
Uint32 src_format;
void *src_pixels;
SDL_Texture* target = WIIU_GetRenderTarget(renderer);
WIIU_TextureData* tdata = (WIIU_TextureData*) target->driverdata;
Uint8 *src_image;
int ret;
/* NOTE: The rect is already adjusted according to the viewport by
* SDL_RenderReadPixels.
*/
SDL_RenderReadPixels */
if (rect->x < 0 || rect->x+rect->w > data->cbuf.surface.width ||
rect->y < 0 || rect->y+rect->h > data->cbuf.surface.height) {
if (rect->x < 0 || rect->x+rect->w > tdata->cbuf.surface.width ||
rect->y < 0 || rect->y+rect->h > tdata->cbuf.surface.height) {
return SDL_SetError("Tried to read outside of surface bounds");
}
src_format = SDL_PIXELFORMAT_RGBA8888; // TODO once working: other formats/checks
src_pixels = (void*)((Uint8 *) data->cbuf.surface.image +
rect->y * data->cbuf.surface.pitch +
rect->x * 4);
src_image = GX2RLockSurfaceEx(&tdata->cbuf.surface, 0, GX2R_RESOURCE_LOCKED_READ_ONLY);
return SDL_ConvertPixels(rect->w, rect->h,
src_format, src_pixels, data->cbuf.surface.pitch,
format, pixels, pitch);
/* Convert and copy the pixels to target buffer */
ret = SDL_ConvertPixels(rect->w, rect->h, target->format,
src_image + rect->y * tdata->cbuf.surface.pitch + rect->x * 4,
tdata->cbuf.surface.pitch,
format, pixels, pitch);
GX2RUnlockSurfaceEx(&tdata->cbuf.surface, 0, GX2R_RESOURCE_LOCKED_READ_ONLY);
return ret;
}
SDL_RenderDriver WIIU_RenderDriver = {
SDL_RenderDriver WIIU_RenderDriver =
{
.CreateRenderer = WIIU_SDL_CreateRenderer,
.info = {
.name = "WiiU GX2",

View File

@@ -1,7 +1,7 @@
/*
Simple DirectMedia Layer
Copyright (C) 2018-2018 Ash Logan <ash@heyquark.com>
Copyright (C) 2018-2018 Roberto Van Eeden <r.r.qwertyuiop.r.r@gmail.com>
Copyright (C) 2018-2019 Ash Logan <ash@heyquark.com>
Copyright (C) 2018-2019 Roberto Van Eeden <r.r.qwertyuiop.r.r@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -19,7 +19,6 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#ifndef SDL_render_wiiu_h
@@ -27,60 +26,91 @@
#include "../SDL_sysrender.h"
#include "SDL_pixels.h"
#include <gx2r/buffer.h>
#include <gx2/context.h>
#include <gx2/sampler.h>
#include <gx2/texture.h>
#include <gx2/surface.h>
#include <gx2/event.h>
typedef struct
/* Driver internal data structures */
typedef struct WIIUVec2 WIIUVec2;
typedef struct WIIUVec3 WIIUVec3;
typedef struct WIIUVec4 WIIUVec4;
typedef struct WIIUPixFmt WIIUPixFmt;
typedef struct WIIU_RenderAllocData WIIU_RenderAllocData;
typedef struct WIIU_TextureDrawData WIIU_TextureDrawData;
typedef struct WIIU_RenderData WIIU_RenderData;
typedef struct WIIU_TextureData WIIU_TextureData;
struct WIIUVec2
{
union { float x, r; };
union { float y, g; };
};
struct WIIUVec3
{
union { float x, r; };
union { float y, g; };
union { float z, b; };
};
struct WIIUVec4
{
union { float x, r; };
union { float y, g; };
union { float z, b; };
union { float w, a; };
};
struct WIIUPixFmt
{
GX2SurfaceFormat fmt;
uint32_t compMap;
};
struct WIIU_RenderAllocData
{
void *next;
int ptr[];
} WIIU_RenderAllocData;
GX2RBuffer buffer;
};
//Driver internal data structures
typedef struct
struct WIIU_TextureDrawData
{
void *next;
WIIU_TextureData *texdata;
};
struct WIIU_RenderData
{
GX2ColorBuffer cbuf;
GX2ContextState *ctx;
WIIU_RenderAllocData *listfree;
float u_viewSize[4];
} WIIU_RenderData;
WIIU_TextureDrawData *listdraw;
WIIUVec4 u_viewSize;
SDL_Texture windowTex;
};
typedef struct
struct WIIU_TextureData
{
GX2Sampler sampler;
GX2Texture texture;
float u_texSize[4];
} WIIU_TextureData;
GX2ColorBuffer cbuf;
WIIUVec4 u_texSize;
WIIUVec4 u_mod;
int isRendering;
};
static inline void *WIIU_AllocRenderData(WIIU_RenderData *r, size_t size) {
WIIU_RenderAllocData *rdata = SDL_malloc(sizeof(WIIU_RenderAllocData) + size);
rdata->next = r->listfree;
r->listfree = rdata;
return (void *)rdata->ptr;
}
static inline void WIIU_FreeRenderData(WIIU_RenderData *r) {
while (r->listfree) {
void *ptr = r->listfree;
r->listfree = r->listfree->next;
SDL_free(ptr);
}
}
//SDL_render API implementation
/* SDL_render API implementation */
SDL_Renderer *WIIU_SDL_CreateRenderer(SDL_Window * window, Uint32 flags);
void WIIU_SDL_WindowEvent(SDL_Renderer * renderer,
const SDL_WindowEvent *event);
int WIIU_SDL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
int WIIU_SDL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
// SDL changes colour/alpha/blend values internally, this is just to notify us.
// We don't care yet. TODO: could update GX2RBuffers less frequently with these?
/*int WIIU_SDL_SetTextureColorMod(SDL_Renderer * renderer,
int WIIU_SDL_SetTextureColorMod(SDL_Renderer * renderer,
SDL_Texture * texture);
int WIIU_SDL_SetTextureAlphaMod(SDL_Renderer * renderer,
SDL_Texture * texture);
int WIIU_SDL_SetTextureBlendMode(SDL_Renderer * renderer,
SDL_Texture * texture);*/
int WIIU_SDL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
int pitch);
@@ -108,28 +138,87 @@ void WIIU_SDL_RenderPresent(SDL_Renderer * renderer);
void WIIU_SDL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
void WIIU_SDL_DestroyRenderer(SDL_Renderer * renderer);
//Utility/helper functions
static inline Uint32 TextureNextPow2(Uint32 w) {
Uint32 n = 2;
if(w == 0)
/* Driver internal functions */
void WIIU_SDL_CreateWindowTex(SDL_Renderer * renderer, SDL_Window * window);
/* Utility/helper functions */
static inline GX2RBuffer * WIIU_AllocRenderData(WIIU_RenderData *r, GX2RBuffer buffer)
{
WIIU_RenderAllocData *rdata = SDL_malloc(sizeof(WIIU_RenderAllocData));
rdata->buffer = buffer;
if (!GX2RCreateBuffer(&rdata->buffer)) {
SDL_free(rdata);
return 0;
while(w > n)
n <<= 1;
return n;
}
rdata->next = r->listfree;
r->listfree = rdata;
return &rdata->buffer;
}
typedef struct WIIUPixFmt {
GX2SurfaceFormat fmt;
uint32_t compMap;
} WIIUPixFmt;
static inline void WIIU_FreeRenderData(WIIU_RenderData *r)
{
while (r->listfree) {
WIIU_RenderAllocData *ptr = r->listfree;
r->listfree = r->listfree->next;
GX2RDestroyBufferEx(&ptr->buffer, 0);
SDL_free(ptr);
}
}
static inline WIIUPixFmt SDLFormatToWIIUFormat(Uint32 format) {
static inline void WIIU_TextureStartRendering(WIIU_RenderData *r, WIIU_TextureData *t)
{
WIIU_TextureDrawData *d = SDL_malloc(sizeof(WIIU_TextureDrawData));
t->isRendering = 1;
d->texdata = t;
d->next = r->listdraw;
r->listdraw = d;
}
static inline void WIIU_TextureDoneRendering(WIIU_RenderData *r)
{
while (r->listdraw) {
WIIU_TextureDrawData *d = r->listdraw;
r->listdraw = r->listdraw->next;
d->texdata->isRendering = 0;
SDL_free(d);
}
}
/* If the texture is currently being rendered and we change the content
before the rendering is finished, the GPU will end up partially drawing
the new data, so we wait for the GPU to finish rendering before
updating the texture */
static inline void WIIU_TextureCheckWaitRendering(WIIU_RenderData *r, WIIU_TextureData *t)
{
if (t->isRendering)
{
GX2DrawDone();
WIIU_TextureDoneRendering(r);
}
}
static inline SDL_Texture * WIIU_GetRenderTarget(SDL_Renderer* renderer)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
if (renderer->target) {
return renderer->target;
}
return &data->windowTex;
}
static inline WIIUPixFmt SDLFormatToWIIUFormat(Uint32 format)
{
WIIUPixFmt outFmt = { /* sane defaults? */
.fmt = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8,
.compMap = 0x00010203,
};
switch (format) {
/* packed16 formats: 4 bits/channel */
/* packed16 formats: 4 bits/channel */
case SDL_PIXELFORMAT_RGB444: /* aka XRGB4444 */
case SDL_PIXELFORMAT_ARGB4444: {
outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R4_G4_B4_A4;
@@ -152,7 +241,7 @@ static inline WIIUPixFmt SDLFormatToWIIUFormat(Uint32 format) {
break;
}
/* packed16 formats: 5 bits/channel */
/* packed16 formats: 5 bits/channel */
case SDL_PIXELFORMAT_RGB555: /* aka XRGB1555 */
case SDL_PIXELFORMAT_ARGB1555: {
outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R5_G5_B5_A1;
@@ -176,7 +265,7 @@ static inline WIIUPixFmt SDLFormatToWIIUFormat(Uint32 format) {
break;
}
/* packed16 formats: 565 */
/* packed16 formats: 565 */
case SDL_PIXELFORMAT_RGB565: {
outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R5_G6_B5;
outFmt.compMap = 0x00010203;
@@ -188,7 +277,7 @@ static inline WIIUPixFmt SDLFormatToWIIUFormat(Uint32 format) {
break;
}
/* packed32 formats */
/* packed32 formats */
case SDL_PIXELFORMAT_RGBA8888:
case SDL_PIXELFORMAT_RGBX8888: {
outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
@@ -218,7 +307,7 @@ static inline WIIUPixFmt SDLFormatToWIIUFormat(Uint32 format) {
break;
}
default: {
/* TODO return an error */
/* TODO return an error */
printf("SDL: WiiU format not recognised (SDL: %08X)\n", format);
break;
}

View File

@@ -0,0 +1,154 @@
/*
Simple DirectMedia Layer
Copyright (C) 2018-2019 Ash Logan <ash@heyquark.com>
Copyright (C) 2018-2019 Roberto Van Eeden <r.r.qwertyuiop.r.r@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_RENDER_WIIU
#include "../../video/wiiu/wiiu_shaders.h"
#include "../SDL_sysrender.h"
#include "SDL_render_wiiu.h"
#include <whb/gfx.h>
#include <gx2/registers.h>
#include <gx2/state.h>
#include <gx2/draw.h>
#include <gx2r/buffer.h>
#include <gx2r/draw.h>
#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 720
static const WIIUVec4 u_viewSize = {.x = (float)SCREEN_WIDTH, .y = (float)SCREEN_HEIGHT};
static void render_scene(SDL_Renderer * renderer)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
WIIU_TextureData *tdata = (WIIU_TextureData *) data->windowTex.driverdata;
float tex_w = tdata->u_texSize.x;
float tex_h = tdata->u_texSize.y;
int win_x, win_y, win_w, win_h;
GX2RBuffer *a_position, *a_texCoord;
WIIUVec2 *a_position_vals, *a_texCoord_vals;
/* Allocate attribute buffers */
a_position = WIIU_AllocRenderData(data, (GX2RBuffer) {
.flags =
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_WRITE,
.elemSize = sizeof(WIIUVec2), /* float x/y for each corner */
.elemCount = 4, /* 4 corners */
});
a_texCoord = WIIU_AllocRenderData(data, (GX2RBuffer) {
.flags =
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_WRITE,
.elemSize = sizeof(WIIUVec2), // float x/y for each corner
.elemCount = 4, // 4 corners
});
/* Calculate and save positions */
if (SDL_GetWindowFlags(renderer->window) & SDL_WINDOW_FULLSCREEN) {
win_x = 0;
win_y = 0;
win_w = SCREEN_WIDTH;
win_h = SCREEN_HEIGHT;
} else {
/* Center */
SDL_GetWindowSize(renderer->window, &win_w, &win_h);
win_x = (SCREEN_WIDTH - win_w) / 2;
win_y = (SCREEN_HEIGHT - win_h) / 2;
}
a_position_vals = GX2RLockBufferEx(a_position, 0);
a_position_vals[0] = (WIIUVec2) {
.x = win_x, .y = win_y
};
a_position_vals[1] = (WIIUVec2) {
.x = win_x + win_w, .y = win_y
};
a_position_vals[2] = (WIIUVec2) {
.x = win_x + win_w, .y = win_y + win_h
};
a_position_vals[3] = (WIIUVec2) {
.x = win_x, .y = win_y + win_h
};
GX2RUnlockBufferEx(a_position, 0);
/* Compute texture coords */
a_texCoord_vals = GX2RLockBufferEx(a_texCoord, 0);
a_texCoord_vals[0] = (WIIUVec2) {.x = 0.0f, .y = tex_h};
a_texCoord_vals[1] = (WIIUVec2) {.x = tex_w, .y = tex_h};
a_texCoord_vals[2] = (WIIUVec2) {.x = tex_w, .y = 0.0f};
a_texCoord_vals[3] = (WIIUVec2) {.x = 0.0f, .y = 0.0f};
GX2RUnlockBufferEx(a_texCoord, 0);
/* Render the window */
WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f);
wiiuSetTextureShader();
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&u_viewSize);
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[1].offset, 4, (uint32_t *)&tdata->u_texSize);
GX2SetPixelUniformReg(wiiuTextureShader.pixelShader->uniformVars[0].offset, 4, (uint32_t*)&tdata->u_mod);
GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0);
GX2RSetAttributeBuffer(a_texCoord, 1, a_texCoord->elemSize, 0);
GX2SetPixelTexture(&tdata->texture, wiiuTextureShader.pixelShader->samplerVars[0].location);
GX2SetPixelSampler(&tdata->sampler, wiiuTextureShader.pixelShader->samplerVars[0].location);
GX2SetColorControl(GX2_LOGIC_OP_COPY, 0x00, FALSE, TRUE);
GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1);
}
void WIIU_SDL_RenderPresent(SDL_Renderer * renderer)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
Uint32 flags = SDL_GetWindowFlags(renderer->window);
WHBGfxBeginRender();
/* Only render to TV if the window is *not* drc-only */
if (!(flags & SDL_WINDOW_WIIU_GAMEPAD_ONLY)) {
WHBGfxBeginRenderTV();
render_scene(renderer);
WHBGfxFinishRenderTV();
}
if (!(flags & SDL_WINDOW_WIIU_TV_ONLY)) {
WHBGfxBeginRenderDRC();
render_scene(renderer);
WHBGfxFinishRenderDRC();
}
WHBGfxFinishRender();
/* Free the list of render and draw data */
WIIU_FreeRenderData(data);
WIIU_TextureDoneRendering(data);
/* Restore SDL context state */
GX2SetContextState(data->ctx);
}
#endif /* SDL_VIDEO_RENDER_WIIU */

View File

@@ -1,7 +1,7 @@
/*
Simple DirectMedia Layer
Copyright (C) 2018-2018 Ash Logan <ash@heyquark.com>
Copyright (C) 2018-2018 Roberto Van Eeden <r.r.qwertyuiop.r.r@gmail.com>
Copyright (C) 2018-2019 Ash Logan <ash@heyquark.com>
Copyright (C) 2018-2019 Roberto Van Eeden <r.r.qwertyuiop.r.r@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -23,42 +23,45 @@
#if SDL_VIDEO_RENDER_WIIU
#include "../../video/wiiu/SDL_wiiuvideo.h"
#include "../SDL_sysrender.h"
#include "SDL_hints.h"
#include "SDL_render_wiiu.h"
#include <gx2/context.h>
#include <gx2/texture.h>
#include <gx2/sampler.h>
#include <gx2/mem.h>
#include <gx2r/surface.h>
#include <gx2r/resource.h>
#include <malloc.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int WIIU_SDL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
WIIUPixFmt gx2_fmt;
BOOL res;
WIIU_TextureData *tdata = (WIIU_TextureData *) SDL_calloc(1, sizeof(*tdata));
if (!tdata)
if (!tdata) {
return SDL_OutOfMemory();
}
/* Setup sampler */
if (texture->scaleMode == SDL_ScaleModeNearest) {
GX2InitSampler(&tdata->sampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_POINT);
} else {
GX2InitSampler(&tdata->sampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_LINEAR);
}
// Setup sampler
GX2InitSampler(&tdata->sampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_LINEAR);
gx2_fmt = SDLFormatToWIIUFormat(texture->format);
/* Setup GX2Texture */
tdata->texture.surface.width = texture->w;
tdata->texture.surface.height = texture->h;
tdata->texture.surface.format = gx2_fmt.fmt;
tdata->texture.surface.depth = 1; //?
tdata->texture.surface.depth = 1;
tdata->texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
tdata->texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
tdata->texture.surface.use = GX2_SURFACE_USE_TEXTURE;
tdata->texture.surface.mipLevels = 1;
tdata->texture.viewNumMips = 1;
tdata->texture.viewNumSlices = 1;
@@ -66,82 +69,145 @@ int WIIU_SDL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
GX2CalcSurfaceSizeAndAlignment(&tdata->texture.surface);
GX2InitTextureRegs(&tdata->texture);
tdata->texture.surface.image = memalign(tdata->texture.surface.alignment, tdata->texture.surface.imageSize);
if(!tdata->texture.surface.image)
{
/* Setup GX2ColorBuffer */
tdata->cbuf.surface = tdata->texture.surface;
tdata->cbuf.viewNumSlices = 1;
GX2InitColorBufferRegs(&tdata->cbuf);
/* Allocate the texture's surface */
res = GX2RCreateSurface(
&tdata->texture.surface,
GX2R_RESOURCE_BIND_TEXTURE | GX2R_RESOURCE_BIND_COLOR_BUFFER |
GX2R_RESOURCE_USAGE_CPU_WRITE | GX2R_RESOURCE_USAGE_CPU_READ |
GX2R_RESOURCE_USAGE_GPU_WRITE | GX2R_RESOURCE_USAGE_GPU_READ
);
if (!res) {
SDL_free(tdata);
return SDL_OutOfMemory();
}
tdata->u_texSize[0] = texture->w;
tdata->u_texSize[1] = texture->h;
/* Allocate a colour buffer, using the same backing buffer */
res = GX2RCreateSurfaceUserMemory(
&tdata->cbuf.surface,
tdata->texture.surface.image,
tdata->texture.surface.mipmaps,
tdata->texture.surface.resourceFlags
);
if (!res) {
GX2RDestroySurfaceEx(&tdata->texture.surface, 0);
SDL_free(tdata);
return SDL_OutOfMemory();
}
/* Initialize texture size uniform */
tdata->u_texSize = (WIIUVec4) {
.x = texture->w,
.y = texture->h,
};
/* Initialize color modifier uniform */
tdata->u_mod = (WIIUVec4) {
.r = (float)texture->r / 255.0f,
.g = (float)texture->g / 255.0f,
.b = (float)texture->b / 255.0f,
.a = (float)texture->a / 255.0f,
};
/* Setup texture driver data */
texture->driverdata = tdata;
return 0;
}
// Somewhat adapted from SDL_render.c: SDL_LockTextureNative
// The app basically wants a pointer to a particular rectangle as well as
// write access to it. We can do that without any special graphics code
/* Somewhat adapted from SDL_render.c: SDL_LockTextureNative
The app basically wants a pointer to a particular rectangle as well as
write access to it. Easy GX2R! */
int WIIU_SDL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, void **pixels, int *pitch)
{
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata;
Uint32 BytesPerPixel = SDL_BYTESPERPIXEL(texture->format);
void* pixel_buffer;
// Calculate pointer to first pixel in rect
*pixels = (void *) ((Uint8 *) tdata->texture.surface.image +
/* Wait for the texture rendering to finish */
WIIU_TextureCheckWaitRendering(data, tdata);
pixel_buffer = GX2RLockSurfaceEx(&tdata->texture.surface, 0, 0);
/* Calculate pointer to first pixel in rect */
*pixels = (void *) ((Uint8 *) pixel_buffer +
rect->y * (tdata->texture.surface.pitch * BytesPerPixel) +
rect->x * BytesPerPixel);
*pitch = (tdata->texture.surface.pitch * BytesPerPixel);
// Not sure we even need to bother keeping track of this
/* Not sure we even need to bother keeping track of this */
texture->locked_rect = *rect;
return 0;
}
void WIIU_SDL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata;
// TODO check this is actually needed
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE,
tdata->texture.surface.image, tdata->texture.surface.imageSize);
GX2RUnlockSurfaceEx(&tdata->texture.surface, 0, 0);
}
int WIIU_SDL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
{
WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata;
Uint32 BytesPerPixel;
Uint8 *src, *dst;
int row;
size_t length;
Uint32 BytesPerPixel = SDL_BYTESPERPIXEL(texture->format);
size_t length = rect->w * BytesPerPixel;
Uint8 *src = (Uint8 *) pixels, *dst;
int row, dst_pitch;
/* We write the rules, and we say all textures are streaming */
WIIU_SDL_LockTexture(renderer, texture, rect, (void**)&dst, &dst_pitch);
BytesPerPixel = SDL_BYTESPERPIXEL(texture->format);
src = (Uint8 *) pixels;
dst = (Uint8 *) tdata->texture.surface.image +
rect->y * (tdata->texture.surface.pitch * BytesPerPixel) +
rect->x * BytesPerPixel;
length = rect->w * BytesPerPixel;
for (row = 0; row < rect->h; ++row) {
SDL_memcpy(dst, src, length);
src += pitch;
dst += (tdata->texture.surface.pitch * BytesPerPixel);
dst += dst_pitch;
}
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE,
tdata->texture.surface.image, tdata->texture.surface.imageSize);
WIIU_SDL_UnlockTexture(renderer, texture);
return 0;
}
int WIIU_SDL_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata;
/* Compute color mod */
tdata->u_mod.r = (float)texture->r / 255.0f;
tdata->u_mod.g = (float)texture->g / 255.0f;
tdata->u_mod.b = (float)texture->b / 255.0f;
return 0;
}
int WIIU_SDL_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata;
/* Compute alpha mod */
tdata->u_mod.a = (float)texture->a / 255.0f;
return 0;
}
void WIIU_SDL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
WIIU_TextureData *tdata;
if (texture == NULL || texture->driverdata == NULL) return;
tdata = (WIIU_TextureData *) texture->driverdata;
free(tdata->texture.surface.image);
WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata;
WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata;
/* Wait for the texture rendering to finish */
WIIU_TextureCheckWaitRendering(data, tdata);
GX2RDestroySurfaceEx(&tdata->cbuf.surface, 0);
GX2RDestroySurfaceEx(&tdata->texture.surface, 0);
SDL_free(tdata);
}

View File

@@ -1,7 +1,7 @@
/*
Simple DirectMedia Layer
Copyright (C) 2018-2018 Ash Logan <ash@heyquark.com>
Copyright (C) 2018-2018 Roberto Van Eeden <r.r.qwertyuiop.r.r@gmail.com>
Copyright (C) 2018-2019 Ash Logan <ash@heyquark.com>
Copyright (C) 2018-2019 Roberto Van Eeden <r.r.qwertyuiop.r.r@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -19,49 +19,44 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_RENDER_WIIU
#include "../../video/wiiu/SDL_wiiuvideo.h"
#include "../SDL_sysrender.h"
#include "SDL_hints.h"
#include "SDL_render_wiiu.h"
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void WIIU_SDL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
{
if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
// Re-init the colour buffer etc. for new window size
// TODO check: what if we're rendering to a texture when this happens?
// SDL may handle this already, see SDL_render.c: SDL_RendererEventWatch
/* Re-init the colour buffer etc. for new window size
TODO check: what if we're rendering to a texture when this happens?
SDL may handle this already, see SDL_render.c: SDL_RendererEventWatch */
WIIU_SDL_CreateWindowTex(renderer, renderer->window);
WIIU_SDL_SetRenderTarget(renderer, NULL);
}
}
// We always output at whatever res the window is.
// This may need to change if SDL_wiiuvideo is ever folded into SDL_render -
// see SDL_*WindowTexture from SDL_video.c for how this could be done
int WIIU_SDL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h) {
/* We always output at whatever res the window is.
This may need to change if SDL_wiiuvideo is ever folded into SDL_render -
see SDL_*WindowTexture from SDL_video.c for how this could be done */
int WIIU_SDL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
{
SDL_GetWindowSize(renderer->window, w, h);
return 0;
}
// We handle all viewport changes in the render functions and shaders, so we
// don't actually have to do anything here. SDL still requires we implement it.
int WIIU_SDL_UpdateViewport(SDL_Renderer * renderer) {
/* We handle all viewport changes in the render functions and shaders, so we
don't actually have to do anything here. SDL still requires we implement it. */
int WIIU_SDL_UpdateViewport(SDL_Renderer * renderer)
{
return 0;
}
// Ideally this should change the GX2SetScissor values, but SetRenderTarget
// needs refactoring first or these get overwritten.
int WIIU_SDL_UpdateClipRect(SDL_Renderer * renderer) {
/* Ideally this should change the GX2SetScissor values, but SetRenderTarget
needs refactoring first or these get overwritten. */
int WIIU_SDL_UpdateClipRect(SDL_Renderer * renderer)
{
return 0;
}

View File

@@ -20,6 +20,13 @@
3. This notice may not be removed or altered from any source distribution.
*/
/* This is basically just a stub at this point - all the magic happens in
* SDL_Render, and the textureframebuffer stuff in SDL_video.c.
* Potentially more could/should be done here, video modes and things.
* Some design work will need to go into the responsibilities of render
* vs video.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_WIIU
@@ -34,16 +41,8 @@
#include "../../events/SDL_keyboard_c.h"
#include "SDL_wiiuvideo.h"
#include <gfd.h>
#include <gx2/draw.h>
#include <gx2/shaders.h>
#include <gx2/mem.h>
#include <gx2/registers.h>
#include <gx2r/draw.h>
#include <gx2r/buffer.h>
#include <whb/proc.h>
#include <whb/gfx.h>
#include <coreinit/memdefaultheap.h>
#include <string.h>
#include <stdint.h>
@@ -53,46 +52,13 @@ static int WIIU_VideoInit(_THIS);
static int WIIU_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
static void WIIU_VideoQuit(_THIS);
static void WIIU_PumpEvents(_THIS);
static int WIIU_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch);
static int WIIU_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects);
static void WIIU_DestroyWindowFramebuffer(_THIS, SDL_Window *window);
#define SCREEN_WIDTH 1280
#define SCREEN_HEIGHT 720
static const float u_viewSize[4] = {(float)SCREEN_WIDTH, (float)SCREEN_HEIGHT};
static const float u_texSize[4] = {(float)SCREEN_WIDTH, (float)SCREEN_HEIGHT};
static const float u_mod[4] = {1.0f, 1.0f, 1.0f, 1.0f};
static const float tex_coord_vb[] =
{
0.0f, (float)SCREEN_HEIGHT,
(float)SCREEN_WIDTH, (float)SCREEN_HEIGHT,
(float)SCREEN_WIDTH, 0.0f,
0.0f, 0.0f,
};
static GX2RBuffer tex_coord_buffer = {
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_READ |
GX2R_RESOURCE_USAGE_CPU_WRITE |
GX2R_RESOURCE_USAGE_GPU_READ,
2 * sizeof(float), 4, NULL
};
static GX2RBuffer position_buffer = {
GX2R_RESOURCE_BIND_VERTEX_BUFFER |
GX2R_RESOURCE_USAGE_CPU_READ |
GX2R_RESOURCE_USAGE_CPU_WRITE |
GX2R_RESOURCE_USAGE_GPU_READ,
2 * sizeof(float), 4, NULL
};
static GX2Sampler sampler = {0};
static int WIIU_VideoInit(_THIS)
{
SDL_DisplayMode mode;
void *buffer = NULL;
WHBProcInit();
WHBGfxInit();
@@ -100,20 +66,6 @@ static int WIIU_VideoInit(_THIS)
// setup shader
wiiuInitTextureShader();
// setup vertex position attribute
GX2RCreateBuffer(&position_buffer);
// setup vertex texture coordinates attribute
GX2RCreateBuffer(&tex_coord_buffer);
buffer = GX2RLockBufferEx(&tex_coord_buffer, 0);
if (buffer) {
memcpy(buffer, tex_coord_vb, tex_coord_buffer.elemSize * tex_coord_buffer.elemCount);
}
GX2RUnlockBufferEx(&tex_coord_buffer, 0);
// initialize a sampler
GX2InitSampler(&sampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_LINEAR);
// add default mode (1280x720)
mode.format = SDL_PIXELFORMAT_RGBA8888;
mode.w = SCREEN_WIDTH;
@@ -130,121 +82,80 @@ static int WIIU_VideoInit(_THIS)
static void WIIU_VideoQuit(_THIS)
{
GX2RDestroyBufferEx(&position_buffer, 0);
GX2RDestroyBufferEx(&tex_coord_buffer, 0);
wiiuFreeTextureShader();
WHBGfxShutdown();
WHBProcShutdown();
}
static int WIIU_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch)
{
WIIU_WindowData *data;
static int WIIU_CreateSDLWindow(_THIS, SDL_Window *window) {
WIIU_VideoDeviceData* ddata = (WIIU_VideoDeviceData*) _this->driverdata;
// hold a pointer to our stuff
data = SDL_calloc(1, sizeof(WIIU_WindowData));
/* If this window wants to be mirrored (no _ONLY flags) */
if (!(window->flags &
(SDL_WINDOW_WIIU_TV_ONLY | SDL_WINDOW_WIIU_GAMEPAD_ONLY))) {
/* Only one window can exist in this state */
if (ddata->drc_window_exists ||
ddata->tv_window_exists ||
ddata->mirrored_window_exists) {
return SDL_SetError(
"WiiU only supports one window when mirroring the TV and "
"Gamepad. https://github.com/yawut/SDL/wiki/Custom-Window-Flags"
);
}
// create a gx2 texture
data->texture.surface.use = GX2_SURFACE_USE_TEXTURE;
data->texture.surface.width = window->w;
data->texture.surface.height = window->h;
data->texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
data->texture.surface.depth = 1;
data->texture.surface.mipLevels = 1;
data->texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
data->texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
data->texture.viewNumSlices = 1;
data->texture.viewNumMips = 1;
data->texture.compMap = 0x00010203;
GX2CalcSurfaceSizeAndAlignment(&data->texture.surface);
GX2InitTextureRegs(&data->texture);
/* Okay! */
ddata->mirrored_window_exists = SDL_TRUE;
data->texture.surface.image = MEMAllocFromDefaultHeapEx(data->texture.surface.imageSize, data->texture.surface.alignment);
/* If this window wants the TV */
} else if (window->flags & SDL_WINDOW_WIIU_TV_ONLY) {
/* Check if a TV window already exists */
if (ddata->tv_window_exists) {
return SDL_SetError(
"WiiU only supports one window on the TV. "
"https://github.com/yawut/SDL/wiki/Custom-Window-Flags"
);
/* Check if a mirrored window exists */
} else if (ddata->mirrored_window_exists) {
return SDL_SetError(
"WiiU only supports one window when mirroring the TV and "
"Gamepad. https://github.com/yawut/SDL/wiki/Custom-Window-Flags"
);
}
// create sdl surface framebuffer
data->surface = SDL_CreateRGBSurfaceWithFormatFrom(
data->texture.surface.image, // pixels
window->w, window->h, // width, height
32, window->w * 4, // depth, pitch
SDL_PIXELFORMAT_RGBA8888 // format
);
ddata->tv_window_exists = SDL_TRUE;
*format = SDL_PIXELFORMAT_RGBA8888;
*pixels = data->surface->pixels;
*pitch = data->surface->pitch;
/* If this window wants the Gamepad */
} else if (window->flags & SDL_WINDOW_WIIU_GAMEPAD_ONLY) {
/* Check if a TV window already exists */
if (ddata->drc_window_exists) {
return SDL_SetError(
"WiiU only supports one window on the Gamepad. "
"https://github.com/yawut/SDL/wiki/Custom-Window-Flags"
);
/* Check if a mirrored window exists */
} else if (ddata->mirrored_window_exists) {
return SDL_SetError(
"WiiU only supports one window when mirroring the TV and "
"Gamepad. https://github.com/yawut/SDL/wiki/Custom-Window-Flags"
);
}
SDL_SetWindowData(window, WIIU_WINDOW_DATA, data);
// inform SDL we're ready to accept inputs
ddata->drc_window_exists = SDL_TRUE;
}
SDL_SetKeyboardFocus(window);
return 0;
}
static void render_scene(WIIU_WindowData *data) {
WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f);
wiiuSetTextureShader();
static void WIIU_DestroyWindow(_THIS, SDL_Window * window) {
WIIU_VideoDeviceData* ddata = (WIIU_VideoDeviceData*) _this->driverdata;
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)u_viewSize);
GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[1].offset, 4, (uint32_t *)u_texSize);
GX2SetPixelUniformReg(wiiuTextureShader.pixelShader->uniformVars[0].offset, 4, (uint32_t*)u_mod);
GX2RSetAttributeBuffer(&position_buffer, 0, position_buffer.elemSize, 0);
GX2RSetAttributeBuffer(&tex_coord_buffer, 1, tex_coord_buffer.elemSize, 0);
GX2SetPixelTexture(&data->texture, wiiuTextureShader.pixelShader->samplerVars[0].location);
GX2SetPixelSampler(&sampler, wiiuTextureShader.pixelShader->samplerVars[0].location);
GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1);
}
static int WIIU_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects)
{
WIIU_WindowData *data = (WIIU_WindowData *) SDL_GetWindowData(window, WIIU_WINDOW_DATA);
Uint32 flags = SDL_GetWindowFlags(window);
float a_position[8];
float* buffer;
int x, y, w, h;
SDL_GetWindowPosition(window, &x, &y);
SDL_GetWindowSize(window, &w, &h);
a_position[0] = (float)x; a_position[1] = (float)y;
a_position[2] = (float)(x + w); a_position[3] = (float)y;
a_position[4] = (float)(x + w); a_position[5] = (float)(y + h);
a_position[6] = (float)x; a_position[7] = (float)(y + h);
buffer = GX2RLockBufferEx(&position_buffer, 0);
if (buffer) {
memcpy(buffer, a_position, position_buffer.elemSize * position_buffer.elemCount);
if (window->flags & SDL_WINDOW_WIIU_TV_ONLY) {
ddata->tv_window_exists = SDL_FALSE;
} else if (window->flags & SDL_WINDOW_WIIU_GAMEPAD_ONLY) {
ddata->drc_window_exists = SDL_FALSE;
} else {
ddata->mirrored_window_exists = SDL_FALSE;
}
GX2RUnlockBufferEx(&position_buffer, 0);
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, data->texture.surface.image, data->texture.surface.imageSize);
WHBGfxBeginRender();
if (!(flags & SDL_WINDOW_WIIU_GAMEPAD_ONLY)) {
WHBGfxBeginRenderTV();
render_scene(data);
WHBGfxFinishRenderTV();
}
if (!(flags & SDL_WINDOW_WIIU_TV_ONLY)) {
WHBGfxBeginRenderDRC();
render_scene(data);
WHBGfxFinishRenderDRC();
}
WHBGfxFinishRender();
return 0;
}
static void WIIU_DestroyWindowFramebuffer(_THIS, SDL_Window *window)
{
WIIU_WindowData *data = (WIIU_WindowData*) SDL_GetWindowData(window, WIIU_WINDOW_DATA);
SDL_FreeSurface(data->surface);
MEMFreeToDefaultHeap(data->texture.surface.image);
SDL_free(data);
}
static int WIIU_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
@@ -263,6 +174,7 @@ static int WIIU_Available(void)
static void WIIU_DeleteDevice(SDL_VideoDevice *device)
{
SDL_free(device->driverdata);
SDL_free(device);
}
@@ -276,13 +188,19 @@ static SDL_VideoDevice *WIIU_CreateDevice(int devindex)
return NULL;
}
device->driverdata = (void*) SDL_calloc(1, sizeof(WIIU_VideoDeviceData));
if (!device->driverdata) {
SDL_OutOfMemory();
SDL_free(device);
return NULL;
}
device->VideoInit = WIIU_VideoInit;
device->VideoQuit = WIIU_VideoQuit;
device->SetDisplayMode = WIIU_SetDisplayMode;
device->PumpEvents = WIIU_PumpEvents;
device->CreateWindowFramebuffer = WIIU_CreateWindowFramebuffer;
device->UpdateWindowFramebuffer = WIIU_UpdateWindowFramebuffer;
device->DestroyWindowFramebuffer = WIIU_DestroyWindowFramebuffer;
device->CreateSDLWindow = WIIU_CreateSDLWindow;
device->DestroyWindow = WIIU_DestroyWindow;
device->free = WIIU_DeleteDevice;

View File

@@ -35,4 +35,11 @@ typedef struct
GX2Texture texture;
} WIIU_WindowData;
typedef struct
{
SDL_bool tv_window_exists;
SDL_bool drc_window_exists;
SDL_bool mirrored_window_exists;
} WIIU_VideoDeviceData;
#endif //SDL_wiiuvideo_h