diff --git a/src/render/wiiu/SDL_rdraw_wiiu.c b/src/render/wiiu/SDL_rdraw_wiiu.c index dd79fd1b1..310a0d6bc 100644 --- a/src/render/wiiu/SDL_rdraw_wiiu.c +++ b/src/render/wiiu/SDL_rdraw_wiiu.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -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 */ diff --git a/src/render/wiiu/SDL_render_wiiu.c b/src/render/wiiu/SDL_render_wiiu.c index 44dbbb8f9..e83dcd362 100644 --- a/src/render/wiiu/SDL_render_wiiu.c +++ b/src/render/wiiu/SDL_render_wiiu.c @@ -1,7 +1,7 @@ /* Simple DirectMedia Layer - Copyright (C) 2018-2018 Ash Logan - Copyright (C) 2018-2018 Roberto Van Eeden + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden 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 +#include #include -#include -#include -#include -#include -#include 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", diff --git a/src/render/wiiu/SDL_render_wiiu.h b/src/render/wiiu/SDL_render_wiiu.h index 22726e7da..a3480bd36 100644 --- a/src/render/wiiu/SDL_render_wiiu.h +++ b/src/render/wiiu/SDL_render_wiiu.h @@ -1,7 +1,7 @@ /* Simple DirectMedia Layer - Copyright (C) 2018-2018 Ash Logan - Copyright (C) 2018-2018 Roberto Van Eeden + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden 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 #include #include +#include +#include +#include -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; } diff --git a/src/render/wiiu/SDL_rpresent_wiiu.c b/src/render/wiiu/SDL_rpresent_wiiu.c new file mode 100644 index 000000000..4e1649ea6 --- /dev/null +++ b/src/render/wiiu/SDL_rpresent_wiiu.c @@ -0,0 +1,154 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden + + 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 +#include +#include +#include +#include +#include + +#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 */ diff --git a/src/render/wiiu/SDL_rtexture_wiiu.c b/src/render/wiiu/SDL_rtexture_wiiu.c index d44338da3..e57e5b10b 100644 --- a/src/render/wiiu/SDL_rtexture_wiiu.c +++ b/src/render/wiiu/SDL_rtexture_wiiu.c @@ -1,7 +1,7 @@ /* Simple DirectMedia Layer - Copyright (C) 2018-2018 Ash Logan - Copyright (C) 2018-2018 Roberto Van Eeden + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden 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 #include #include #include +#include +#include #include -#include #include -#include -#include -#include 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); } diff --git a/src/render/wiiu/SDL_rwindow_wiiu.c b/src/render/wiiu/SDL_rwindow_wiiu.c index 364fb25d3..fff15be94 100644 --- a/src/render/wiiu/SDL_rwindow_wiiu.c +++ b/src/render/wiiu/SDL_rwindow_wiiu.c @@ -1,7 +1,7 @@ /* Simple DirectMedia Layer - Copyright (C) 2018-2018 Ash Logan - Copyright (C) 2018-2018 Roberto Van Eeden + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden 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 -#include -#include -#include -#include - 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; } diff --git a/src/video/wiiu/SDL_wiiuvideo.c b/src/video/wiiu/SDL_wiiuvideo.c index a9feac0df..3a04271ba 100644 --- a/src/video/wiiu/SDL_wiiuvideo.c +++ b/src/video/wiiu/SDL_wiiuvideo.c @@ -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 -#include -#include -#include -#include -#include -#include #include #include -#include #include #include @@ -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; diff --git a/src/video/wiiu/SDL_wiiuvideo.h b/src/video/wiiu/SDL_wiiuvideo.h index bf5e1a9f7..3cbf3df4c 100644 --- a/src/video/wiiu/SDL_wiiuvideo.h +++ b/src/video/wiiu/SDL_wiiuvideo.h @@ -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