mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-02-14 15:53:14 +00:00
Restore support for the Nokia N-Gage (#12148)
This commit is contained in:
committed by
GitHub
parent
26f9940f82
commit
7ae64592c9
@@ -120,6 +120,9 @@ static const SDL_RenderDriver *render_drivers[] = {
|
||||
#ifdef SDL_VIDEO_RENDER_METAL
|
||||
&METAL_RenderDriver,
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_RENDER_NGAGE
|
||||
&NGAGE_RenderDriver,
|
||||
#endif
|
||||
#ifdef SDL_VIDEO_RENDER_OGL
|
||||
&GL_RenderDriver,
|
||||
#endif
|
||||
|
||||
@@ -357,6 +357,7 @@ extern SDL_RenderDriver D3D12_RenderDriver;
|
||||
extern SDL_RenderDriver GL_RenderDriver;
|
||||
extern SDL_RenderDriver GLES2_RenderDriver;
|
||||
extern SDL_RenderDriver METAL_RenderDriver;
|
||||
extern SDL_RenderDriver NGAGE_RenderDriver;
|
||||
extern SDL_RenderDriver VULKAN_RenderDriver;
|
||||
extern SDL_RenderDriver PS2_RenderDriver;
|
||||
extern SDL_RenderDriver PSP_RenderDriver;
|
||||
|
||||
544
src/render/ngage/SDL_render_ngage.c
Normal file
544
src/render/ngage/SDL_render_ngage.c
Normal file
@@ -0,0 +1,544 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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"
|
||||
|
||||
#ifdef SDL_VIDEO_RENDER_NGAGE
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#ifndef Int2Fix
|
||||
#define Int2Fix(i) ((i) << 16)
|
||||
#endif
|
||||
|
||||
#ifndef Fix2Int
|
||||
#define Fix2Int(i) ((((unsigned int)(i) > 0xFFFF0000) ? 0 : ((i) >> 16)))
|
||||
#endif
|
||||
|
||||
#ifndef Fix2Real
|
||||
#define Fix2Real(i) ((i) / 65536.0)
|
||||
#endif
|
||||
|
||||
#ifndef Real2Fix
|
||||
#define Real2Fix(i) ((int)((i) * 65536.0))
|
||||
#endif
|
||||
|
||||
#include "../SDL_sysrender.h"
|
||||
#include "SDL_render_ngage_c.h"
|
||||
|
||||
static void NGAGE_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event);
|
||||
static bool NGAGE_GetOutputSize(SDL_Renderer *renderer, int *w, int *h);
|
||||
static bool NGAGE_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode);
|
||||
static bool NGAGE_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props);
|
||||
static bool NGAGE_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
|
||||
static bool NGAGE_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd);
|
||||
static bool NGAGE_QueueDrawVertices(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count);
|
||||
static bool NGAGE_QueueFillRects(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count);
|
||||
static bool NGAGE_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect);
|
||||
static bool NGAGE_QueueCopyEx(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_FRect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y);
|
||||
static bool NGAGE_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, int num_vertices, const void *indices, int num_indices, int size_indices, float scale_x, float scale_y);
|
||||
|
||||
static void NGAGE_InvalidateCachedState(SDL_Renderer *renderer);
|
||||
static bool NGAGE_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
|
||||
static bool NGAGE_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch);
|
||||
|
||||
static bool NGAGE_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch);
|
||||
static void NGAGE_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture);
|
||||
static void NGAGE_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode);
|
||||
static bool NGAGE_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture);
|
||||
static SDL_Surface *NGAGE_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect);
|
||||
static bool NGAGE_RenderPresent(SDL_Renderer *renderer);
|
||||
static void NGAGE_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
|
||||
|
||||
static void NGAGE_DestroyRenderer(SDL_Renderer *renderer);
|
||||
|
||||
static bool NGAGE_SetVSync(SDL_Renderer *renderer, int vsync);
|
||||
|
||||
static bool NGAGE_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
|
||||
{
|
||||
SDL_SetupRendererColorspace(renderer, create_props);
|
||||
|
||||
if (renderer->output_colorspace != SDL_COLORSPACE_RGB_DEFAULT) {
|
||||
return SDL_SetError("Unsupported output colorspace");
|
||||
}
|
||||
|
||||
NGAGE_RendererData *phdata = SDL_calloc(1, sizeof(NGAGE_RendererData));
|
||||
if (!phdata) {
|
||||
SDL_OutOfMemory();
|
||||
return false;
|
||||
}
|
||||
|
||||
renderer->WindowEvent = NGAGE_WindowEvent;
|
||||
renderer->GetOutputSize = NGAGE_GetOutputSize;
|
||||
renderer->SupportsBlendMode = NGAGE_SupportsBlendMode;
|
||||
renderer->CreateTexture = NGAGE_CreateTexture;
|
||||
renderer->QueueSetViewport = NGAGE_QueueSetViewport;
|
||||
renderer->QueueSetDrawColor = NGAGE_QueueSetDrawColor;
|
||||
renderer->QueueDrawPoints = NGAGE_QueueDrawVertices;
|
||||
renderer->QueueDrawLines = NGAGE_QueueDrawVertices;
|
||||
renderer->QueueFillRects = NGAGE_QueueFillRects;
|
||||
renderer->QueueCopy = NGAGE_QueueCopy;
|
||||
renderer->QueueCopyEx = NGAGE_QueueCopyEx;
|
||||
renderer->QueueGeometry = NGAGE_QueueGeometry;
|
||||
|
||||
renderer->InvalidateCachedState = NGAGE_InvalidateCachedState;
|
||||
renderer->RunCommandQueue = NGAGE_RunCommandQueue;
|
||||
renderer->UpdateTexture = NGAGE_UpdateTexture;
|
||||
renderer->LockTexture = NGAGE_LockTexture;
|
||||
renderer->UnlockTexture = NGAGE_UnlockTexture;
|
||||
// renderer->SetTextureScaleMode = NGAGE_SetTextureScaleMode;
|
||||
renderer->SetRenderTarget = NGAGE_SetRenderTarget;
|
||||
renderer->RenderReadPixels = NGAGE_RenderReadPixels;
|
||||
renderer->RenderPresent = NGAGE_RenderPresent;
|
||||
renderer->DestroyTexture = NGAGE_DestroyTexture;
|
||||
|
||||
renderer->DestroyRenderer = NGAGE_DestroyRenderer;
|
||||
|
||||
renderer->SetVSync = NGAGE_SetVSync;
|
||||
|
||||
renderer->name = NGAGE_RenderDriver.name;
|
||||
renderer->window = window;
|
||||
renderer->internal = phdata;
|
||||
|
||||
SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB4444);
|
||||
SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 256);
|
||||
SDL_SetHintWithPriority(SDL_HINT_RENDER_LINE_METHOD, "2", SDL_HINT_OVERRIDE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SDL_RenderDriver NGAGE_RenderDriver = {
|
||||
NGAGE_CreateRenderer,
|
||||
"N-Gage"
|
||||
};
|
||||
|
||||
static void NGAGE_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static bool NGAGE_GetOutputSize(SDL_Renderer *renderer, int *w, int *h)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NGAGE_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode)
|
||||
{
|
||||
switch (blendMode) {
|
||||
case SDL_BLENDMODE_NONE:
|
||||
case SDL_BLENDMODE_MOD:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool NGAGE_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
|
||||
{
|
||||
NGAGE_TextureData *data = (NGAGE_TextureData *)SDL_calloc(1, sizeof(*data));
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NGAGE_CreateTextureData(data, texture->w, texture->h)) {
|
||||
SDL_free(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_Surface *surface = SDL_CreateSurface(texture->w, texture->h, texture->format);
|
||||
if (!surface) {
|
||||
SDL_free(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
data->surface = surface;
|
||||
texture->internal = data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NGAGE_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
|
||||
{
|
||||
if (!cmd->data.viewport.rect.w && !cmd->data.viewport.rect.h) {
|
||||
SDL_Rect viewport = { 0, 0, NGAGE_SCREEN_WIDTH, NGAGE_SCREEN_HEIGHT };
|
||||
SDL_SetRenderViewport(renderer, &viewport);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NGAGE_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NGAGE_QueueDrawVertices(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
|
||||
{
|
||||
NGAGE_Vertex *verts = (NGAGE_Vertex *)SDL_AllocateRenderVertices(renderer, count * sizeof(NGAGE_Vertex), 0, &cmd->data.draw.first);
|
||||
if (!verts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cmd->data.draw.count = count;
|
||||
|
||||
for (int i = 0; i < count; i++, points++) {
|
||||
int fixed_x = Real2Fix(points->x);
|
||||
int fixed_y = Real2Fix(points->y);
|
||||
|
||||
verts[i].x = Fix2Int(fixed_x);
|
||||
verts[i].y = Fix2Int(fixed_y);
|
||||
|
||||
Uint32 color = NGAGE_ConvertColor(cmd->data.draw.color.r, cmd->data.draw.color.g, cmd->data.draw.color.b, cmd->data.draw.color.a, cmd->data.draw.color_scale);
|
||||
|
||||
verts[i].color.a = (Uint8)(color >> 24);
|
||||
verts[i].color.b = (Uint8)(color >> 16);
|
||||
verts[i].color.g = (Uint8)(color >> 8);
|
||||
verts[i].color.r = (Uint8)color;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NGAGE_QueueFillRects(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count)
|
||||
{
|
||||
NGAGE_Vertex *verts = (NGAGE_Vertex *)SDL_AllocateRenderVertices(renderer, count * 2 * sizeof(NGAGE_Vertex), 0, &cmd->data.draw.first);
|
||||
if (!verts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cmd->data.draw.count = count;
|
||||
|
||||
for (int i = 0; i < count; i++, rects++) {
|
||||
verts[i * 2].x = Real2Fix(rects->x);
|
||||
verts[i * 2].y = Real2Fix(rects->y);
|
||||
verts[i * 2 + 1].x = Real2Fix(rects->w);
|
||||
verts[i * 2 + 1].y = Real2Fix(rects->h);
|
||||
|
||||
verts[i * 2].x = Fix2Int(verts[i * 2].x);
|
||||
verts[i * 2].y = Fix2Int(verts[i * 2].y);
|
||||
verts[i * 2 + 1].x = Fix2Int(verts[i * 2 + 1].x);
|
||||
verts[i * 2 + 1].y = Fix2Int(verts[i * 2 + 1].y);
|
||||
|
||||
Uint32 color = NGAGE_ConvertColor(cmd->data.draw.color.r, cmd->data.draw.color.g, cmd->data.draw.color.b, cmd->data.draw.color.a, cmd->data.draw.color_scale);
|
||||
|
||||
verts[i * 2].color.a = (Uint8)(color >> 24);
|
||||
verts[i * 2].color.b = (Uint8)(color >> 16);
|
||||
verts[i * 2].color.g = (Uint8)(color >> 8);
|
||||
verts[i * 2].color.r = (Uint8)color;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NGAGE_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect)
|
||||
{
|
||||
SDL_Rect *verts = (SDL_Rect *)SDL_AllocateRenderVertices(renderer, 2 * sizeof(SDL_Rect), 0, &cmd->data.draw.first);
|
||||
|
||||
if (!verts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cmd->data.draw.count = 1;
|
||||
|
||||
verts->x = (int)srcrect->x;
|
||||
verts->y = (int)srcrect->y;
|
||||
verts->w = (int)srcrect->w;
|
||||
verts->h = (int)srcrect->h;
|
||||
|
||||
verts++;
|
||||
|
||||
verts->x = (int)dstrect->x;
|
||||
verts->y = (int)dstrect->y;
|
||||
verts->w = (int)dstrect->w;
|
||||
verts->h = (int)dstrect->h;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NGAGE_QueueCopyEx(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_FRect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_FlipMode flip, float scale_x, float scale_y)
|
||||
{
|
||||
NGAGE_CopyExData *verts = (NGAGE_CopyExData *)SDL_AllocateRenderVertices(renderer, sizeof(NGAGE_CopyExData), 0, &cmd->data.draw.first);
|
||||
|
||||
if (!verts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cmd->data.draw.count = 1;
|
||||
|
||||
verts->srcrect.x = (int)srcquad->x;
|
||||
verts->srcrect.y = (int)srcquad->y;
|
||||
verts->srcrect.w = (int)srcquad->w;
|
||||
verts->srcrect.h = (int)srcquad->h;
|
||||
verts->dstrect.x = (int)dstrect->x;
|
||||
verts->dstrect.y = (int)dstrect->y;
|
||||
verts->dstrect.w = (int)dstrect->w;
|
||||
verts->dstrect.h = (int)dstrect->h;
|
||||
|
||||
verts->angle = Real2Fix(angle);
|
||||
verts->center.x = Real2Fix(center->x);
|
||||
verts->center.y = Real2Fix(center->y);
|
||||
verts->scale_x = Real2Fix(scale_x);
|
||||
verts->scale_y = Real2Fix(scale_y);
|
||||
|
||||
verts->flip = flip;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NGAGE_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride, int num_vertices, const void *indices, int num_indices, int size_indices, float scale_x, float scale_y)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void NGAGE_InvalidateCachedState(SDL_Renderer *renderer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static bool NGAGE_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
|
||||
{
|
||||
NGAGE_RendererData *phdata = (NGAGE_RendererData *)renderer->internal;
|
||||
if (!phdata) {
|
||||
return false;
|
||||
}
|
||||
phdata->viewport = 0;
|
||||
|
||||
while (cmd) {
|
||||
switch (cmd->command) {
|
||||
case SDL_RENDERCMD_NO_OP:
|
||||
break;
|
||||
case SDL_RENDERCMD_SETVIEWPORT:
|
||||
phdata->viewport = &cmd->data.viewport.rect;
|
||||
break;
|
||||
|
||||
case SDL_RENDERCMD_SETCLIPRECT:
|
||||
{
|
||||
const SDL_Rect *rect = &cmd->data.cliprect.rect;
|
||||
|
||||
if (cmd->data.cliprect.enabled) {
|
||||
NGAGE_SetClipRect(rect);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_SETDRAWCOLOR:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_CLEAR:
|
||||
{
|
||||
Uint32 color = NGAGE_ConvertColor(cmd->data.color.color.r, cmd->data.color.color.g, cmd->data.color.color.b, cmd->data.color.color.a, cmd->data.color.color_scale);
|
||||
|
||||
NGAGE_Clear(color);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_DRAW_POINTS:
|
||||
{
|
||||
NGAGE_Vertex *verts = (NGAGE_Vertex *)(((Uint8 *)vertices) + cmd->data.draw.first);
|
||||
const int count = cmd->data.draw.count;
|
||||
|
||||
// Apply viewport.
|
||||
if (phdata->viewport && (phdata->viewport->x || phdata->viewport->y)) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
verts[i].x += phdata->viewport->x;
|
||||
verts[i].y += phdata->viewport->y;
|
||||
}
|
||||
}
|
||||
|
||||
NGAGE_DrawPoints(verts, count);
|
||||
break;
|
||||
}
|
||||
case SDL_RENDERCMD_DRAW_LINES:
|
||||
{
|
||||
NGAGE_Vertex *verts = (NGAGE_Vertex *)(((Uint8 *)vertices) + cmd->data.draw.first);
|
||||
const int count = cmd->data.draw.count;
|
||||
|
||||
// Apply viewport.
|
||||
if (phdata->viewport && (phdata->viewport->x || phdata->viewport->y)) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
verts[i].x += phdata->viewport->x;
|
||||
verts[i].y += phdata->viewport->y;
|
||||
}
|
||||
}
|
||||
|
||||
NGAGE_DrawLines(verts, count);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_FILL_RECTS:
|
||||
{
|
||||
NGAGE_Vertex *verts = (NGAGE_Vertex *)(((Uint8 *)vertices) + cmd->data.draw.first);
|
||||
const int count = cmd->data.draw.count;
|
||||
|
||||
// Apply viewport.
|
||||
if (phdata->viewport && (phdata->viewport->x || phdata->viewport->y)) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
verts[i].x += phdata->viewport->x;
|
||||
verts[i].y += phdata->viewport->y;
|
||||
}
|
||||
}
|
||||
|
||||
NGAGE_FillRects(verts, count);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_COPY:
|
||||
{
|
||||
SDL_Rect *verts = (SDL_Rect *)(((Uint8 *)vertices) + cmd->data.draw.first);
|
||||
SDL_Rect *srcrect = verts;
|
||||
SDL_Rect *dstrect = verts + 1;
|
||||
SDL_Texture *texture = cmd->data.draw.texture;
|
||||
|
||||
// Apply viewport.
|
||||
if (phdata->viewport && (phdata->viewport->x || phdata->viewport->y)) {
|
||||
dstrect->x += phdata->viewport->x;
|
||||
dstrect->y += phdata->viewport->y;
|
||||
}
|
||||
|
||||
NGAGE_Copy(renderer, texture, srcrect, dstrect);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_COPY_EX:
|
||||
{
|
||||
NGAGE_CopyExData *copydata = (NGAGE_CopyExData *)(((Uint8 *)vertices) + cmd->data.draw.first);
|
||||
SDL_Texture *texture = cmd->data.draw.texture;
|
||||
|
||||
// Apply viewport.
|
||||
if (phdata->viewport && (phdata->viewport->x || phdata->viewport->y)) {
|
||||
copydata->dstrect.x += phdata->viewport->x;
|
||||
copydata->dstrect.y += phdata->viewport->y;
|
||||
}
|
||||
|
||||
NGAGE_CopyEx(renderer, texture, copydata);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_RENDERCMD_GEOMETRY:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
cmd = cmd->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NGAGE_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
|
||||
{
|
||||
NGAGE_TextureData *phdata = (NGAGE_TextureData *)texture->internal;
|
||||
|
||||
SDL_Surface *surface = phdata->surface;
|
||||
Uint8 *src, *dst;
|
||||
int row;
|
||||
size_t length;
|
||||
|
||||
if (SDL_MUSTLOCK(surface)) {
|
||||
if (!SDL_LockSurface(surface)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
src = (Uint8 *)pixels;
|
||||
dst = (Uint8 *)surface->pixels +
|
||||
rect->y * surface->pitch +
|
||||
rect->x * surface->fmt->bytes_per_pixel;
|
||||
|
||||
length = (size_t)rect->w * surface->fmt->bytes_per_pixel;
|
||||
for (row = 0; row < rect->h; ++row) {
|
||||
SDL_memcpy(dst, src, length);
|
||||
src += pitch;
|
||||
dst += surface->pitch;
|
||||
}
|
||||
if (SDL_MUSTLOCK(surface)) {
|
||||
SDL_UnlockSurface(surface);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NGAGE_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
|
||||
{
|
||||
NGAGE_TextureData *phdata = (NGAGE_TextureData *)texture->internal;
|
||||
SDL_Surface *surface = phdata->surface;
|
||||
|
||||
*pixels =
|
||||
(void *)((Uint8 *)surface->pixels + rect->y * surface->pitch +
|
||||
rect->x * surface->fmt->bytes_per_pixel);
|
||||
*pitch = surface->pitch;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void NGAGE_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
{
|
||||
}
|
||||
|
||||
static void NGAGE_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
|
||||
{
|
||||
}
|
||||
|
||||
static bool NGAGE_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static SDL_Surface *NGAGE_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
|
||||
{
|
||||
return (SDL_Surface *)0;
|
||||
}
|
||||
|
||||
static bool NGAGE_RenderPresent(SDL_Renderer *renderer)
|
||||
{
|
||||
NGAGE_Flip();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void NGAGE_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||
{
|
||||
NGAGE_TextureData *data = (NGAGE_TextureData *)texture->internal;
|
||||
if (data) {
|
||||
SDL_DestroySurface(data->surface);
|
||||
NGAGE_DestroyTextureData(data);
|
||||
SDL_free(data);
|
||||
texture->internal = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void NGAGE_DestroyRenderer(SDL_Renderer *renderer)
|
||||
{
|
||||
NGAGE_RendererData *phdata = (NGAGE_RendererData *)renderer->internal;
|
||||
if (phdata) {
|
||||
SDL_free(phdata);
|
||||
renderer->internal = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool NGAGE_SetVSync(SDL_Renderer *renderer, int vsync)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // SDL_VIDEO_RENDER_NGAGE
|
||||
744
src/render/ngage/SDL_render_ngage.cpp
Normal file
744
src/render/ngage/SDL_render_ngage.cpp
Normal file
@@ -0,0 +1,744 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../SDL_sysrender.h"
|
||||
#include "SDL_internal.h"
|
||||
#include "SDL_render_ngage_c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SDL_VIDEO_RENDER_NGAGE
|
||||
|
||||
#include "SDL_render_ngage_c.hpp"
|
||||
#include "SDL_render_ops.hpp"
|
||||
|
||||
const TUint32 WindowClientHandle = 0x571D0A;
|
||||
|
||||
extern CRenderer *gRenderer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void NGAGE_Clear(const Uint32 color)
|
||||
{
|
||||
gRenderer->Clear(color);
|
||||
}
|
||||
|
||||
bool NGAGE_Copy(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Rect *srcrect, SDL_Rect *dstrect)
|
||||
{
|
||||
return gRenderer->Copy(renderer, texture, srcrect, dstrect);
|
||||
}
|
||||
|
||||
bool NGAGE_CopyEx(SDL_Renderer *renderer, SDL_Texture *texture, NGAGE_CopyExData *copydata)
|
||||
{
|
||||
return gRenderer->CopyEx(renderer, texture, copydata);
|
||||
}
|
||||
|
||||
bool NGAGE_CreateTextureData(NGAGE_TextureData *data, const int width, const int height)
|
||||
{
|
||||
return gRenderer->CreateTextureData(data, width, height);
|
||||
}
|
||||
|
||||
void NGAGE_DestroyTextureData(NGAGE_TextureData *data)
|
||||
{
|
||||
if (data) {
|
||||
delete data->bitmap;
|
||||
data->bitmap = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void NGAGE_DrawLines(NGAGE_Vertex *verts, const int count)
|
||||
{
|
||||
gRenderer->DrawLines(verts, count);
|
||||
}
|
||||
|
||||
void NGAGE_DrawPoints(NGAGE_Vertex *verts, const int count)
|
||||
{
|
||||
gRenderer->DrawPoints(verts, count);
|
||||
}
|
||||
|
||||
void NGAGE_FillRects(NGAGE_Vertex *verts, const int count)
|
||||
{
|
||||
gRenderer->FillRects(verts, count);
|
||||
}
|
||||
|
||||
void NGAGE_Flip()
|
||||
{
|
||||
gRenderer->Flip();
|
||||
}
|
||||
|
||||
void NGAGE_SetClipRect(const SDL_Rect *rect)
|
||||
{
|
||||
gRenderer->SetClipRect(rect->x, rect->y, rect->w, rect->h);
|
||||
}
|
||||
|
||||
void NGAGE_SetDrawColor(const Uint32 color)
|
||||
{
|
||||
if (gRenderer) {
|
||||
gRenderer->SetDrawColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
void NGAGE_PumpEventsInternal()
|
||||
{
|
||||
gRenderer->PumpEvents();
|
||||
}
|
||||
|
||||
void NGAGE_SuspendScreenSaverInternal(bool suspend)
|
||||
{
|
||||
gRenderer->SuspendScreenSaver(suspend);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
CRenderer *CRenderer::NewL()
|
||||
{
|
||||
CRenderer *self = new (ELeave) CRenderer();
|
||||
CleanupStack::PushL(self);
|
||||
self->ConstructL();
|
||||
CleanupStack::Pop(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
CRenderer::CRenderer() : iRenderer(0), iDirectScreen(0), iScreenGc(0), iWsSession(), iWsWindowGroup(), iWsWindowGroupID(0), iWsWindow(), iWsScreen(0), iWsEventStatus(), iWsEvent(), iShowFPS(EFalse), iFPS(0), iFont(0) {}
|
||||
|
||||
CRenderer::~CRenderer()
|
||||
{
|
||||
delete iRenderer;
|
||||
iRenderer = 0;
|
||||
}
|
||||
|
||||
void CRenderer::ConstructL()
|
||||
{
|
||||
TInt error = KErrNone;
|
||||
|
||||
error = iWsSession.Connect();
|
||||
if (error != KErrNone) {
|
||||
SDL_Log("Failed to connect to window server: %d", error);
|
||||
User::Leave(error);
|
||||
}
|
||||
|
||||
iWsScreen = new (ELeave) CWsScreenDevice(iWsSession);
|
||||
error = iWsScreen->Construct();
|
||||
if (error != KErrNone) {
|
||||
SDL_Log("Failed to construct screen device: %d", error);
|
||||
User::Leave(error);
|
||||
}
|
||||
|
||||
iWsWindowGroup = RWindowGroup(iWsSession);
|
||||
error = iWsWindowGroup.Construct(WindowClientHandle);
|
||||
if (error != KErrNone) {
|
||||
SDL_Log("Failed to construct window group: %d", error);
|
||||
User::Leave(error);
|
||||
}
|
||||
iWsWindowGroup.SetOrdinalPosition(0);
|
||||
|
||||
RProcess thisProcess;
|
||||
TParse exeName;
|
||||
exeName.Set(thisProcess.FileName(), NULL, NULL);
|
||||
TBuf<32> winGroupName;
|
||||
winGroupName.Append(0);
|
||||
winGroupName.Append(0);
|
||||
winGroupName.Append(0); // UID
|
||||
winGroupName.Append(0);
|
||||
winGroupName.Append(exeName.Name()); // Caption
|
||||
winGroupName.Append(0);
|
||||
winGroupName.Append(0); // DOC name
|
||||
iWsWindowGroup.SetName(winGroupName);
|
||||
|
||||
iWsWindow = RWindow(iWsSession);
|
||||
error = iWsWindow.Construct(iWsWindowGroup, WindowClientHandle - 1);
|
||||
if (error != KErrNone) {
|
||||
SDL_Log("Failed to construct window: %d", error);
|
||||
User::Leave(error);
|
||||
}
|
||||
iWsWindow.SetBackgroundColor(KRgbWhite);
|
||||
iWsWindow.SetRequiredDisplayMode(EColor4K);
|
||||
iWsWindow.Activate();
|
||||
iWsWindow.SetSize(iWsScreen->SizeInPixels());
|
||||
iWsWindow.SetVisible(ETrue);
|
||||
|
||||
iWsWindowGroupID = iWsWindowGroup.Identifier();
|
||||
|
||||
TRAPD(errc, iRenderer = iRenderer->NewL());
|
||||
if (errc != KErrNone) {
|
||||
SDL_Log("Failed to create renderer: %d", errc);
|
||||
return;
|
||||
}
|
||||
|
||||
iDirectScreen = CDirectScreenAccess::NewL(
|
||||
iWsSession,
|
||||
*(iWsScreen),
|
||||
iWsWindow, *this);
|
||||
|
||||
// Select font.
|
||||
TFontSpec fontSpec(_L("LatinBold12"), 12);
|
||||
TInt errd = iWsScreen->GetNearestFontInTwips((CFont *&)iFont, fontSpec);
|
||||
if (errd != KErrNone) {
|
||||
SDL_Log("Failed to get font: %d", errd);
|
||||
return;
|
||||
}
|
||||
|
||||
// Activate events.
|
||||
iWsEventStatus = KRequestPending;
|
||||
iWsSession.EventReady(&iWsEventStatus);
|
||||
|
||||
DisableKeyBlocking();
|
||||
|
||||
iIsFocused = ETrue;
|
||||
iShowFPS = EFalse;
|
||||
iSuspendScreenSaver = EFalse;
|
||||
|
||||
if (!iDirectScreen->IsActive()) {
|
||||
TRAPD(err, iDirectScreen->StartL());
|
||||
if (KErrNone != err) {
|
||||
return;
|
||||
}
|
||||
iDirectScreen->ScreenDevice()->SetAutoUpdate(ETrue);
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::Restart(RDirectScreenAccess::TTerminationReasons aReason)
|
||||
{
|
||||
if (!iDirectScreen->IsActive()) {
|
||||
TRAPD(err, iDirectScreen->StartL());
|
||||
if (KErrNone != err) {
|
||||
return;
|
||||
}
|
||||
iDirectScreen->ScreenDevice()->SetAutoUpdate(ETrue);
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::AbortNow(RDirectScreenAccess::TTerminationReasons aReason)
|
||||
{
|
||||
if (iDirectScreen->IsActive()) {
|
||||
iDirectScreen->Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::Clear(TUint32 iColor)
|
||||
{
|
||||
if (iRenderer && iRenderer->Gc()) {
|
||||
iRenderer->Gc()->SetBrushColor(iColor);
|
||||
iRenderer->Gc()->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
Uint32 NGAGE_ConvertColor(float r, float g, float b, float a, float color_scale)
|
||||
{
|
||||
TFixed ff = 255 << 16; // 255.f
|
||||
|
||||
TFixed scalef = Real2Fix(color_scale);
|
||||
TFixed rf = Real2Fix(r);
|
||||
TFixed gf = Real2Fix(g);
|
||||
TFixed bf = Real2Fix(b);
|
||||
TFixed af = Real2Fix(a);
|
||||
|
||||
rf = FixMul(rf, scalef);
|
||||
gf = FixMul(gf, scalef);
|
||||
bf = FixMul(bf, scalef);
|
||||
|
||||
rf = SDL_clamp(rf, 0, ff);
|
||||
gf = SDL_clamp(gf, 0, ff);
|
||||
bf = SDL_clamp(bf, 0, ff);
|
||||
af = SDL_clamp(af, 0, ff);
|
||||
|
||||
rf = FixMul(rf, ff) >> 16;
|
||||
gf = FixMul(gf, ff) >> 16;
|
||||
bf = FixMul(bf, ff) >> 16;
|
||||
af = FixMul(af, ff) >> 16;
|
||||
|
||||
return (af << 24) | (bf << 16) | (gf << 8) | rf;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CRenderer::Copy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect)
|
||||
{
|
||||
if (!texture) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NGAGE_TextureData *phdata = (NGAGE_TextureData *)texture->internal;
|
||||
if (!phdata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_FColor *c = &texture->color;
|
||||
int w = phdata->surface->w;
|
||||
int h = phdata->surface->h;
|
||||
int pitch = phdata->surface->pitch;
|
||||
void *source = phdata->surface->pixels;
|
||||
void *dest;
|
||||
|
||||
if (!source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *pixel_buffer_a = SDL_calloc(1, pitch * h);
|
||||
if (!pixel_buffer_a) {
|
||||
return false;
|
||||
}
|
||||
dest = pixel_buffer_a;
|
||||
|
||||
void *pixel_buffer_b = SDL_calloc(1, pitch * h);
|
||||
if (!pixel_buffer_b) {
|
||||
SDL_free(pixel_buffer_a);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c->a != 1.f || c->r != 1.f || c->g != 1.f || c->b != 1.f) {
|
||||
ApplyColorMod(dest, source, pitch, w, h, texture->color);
|
||||
|
||||
source = dest;
|
||||
}
|
||||
|
||||
float sx;
|
||||
float sy;
|
||||
SDL_GetRenderScale(renderer, &sx, &sy);
|
||||
|
||||
if (sx != 1.f || sy != 1.f) {
|
||||
TFixed scale_x = Real2Fix(sx);
|
||||
TFixed scale_y = Real2Fix(sy);
|
||||
TFixed center_x = Int2Fix(w / 2);
|
||||
TFixed center_y = Int2Fix(h / 2);
|
||||
|
||||
dest == pixel_buffer_a ? dest = pixel_buffer_b : dest = pixel_buffer_a;
|
||||
|
||||
ApplyScale(dest, source, pitch, w, h, center_x, center_y, scale_x, scale_y);
|
||||
|
||||
source = dest;
|
||||
}
|
||||
|
||||
Mem::Copy(phdata->bitmap->DataAddress(), source, pitch * h);
|
||||
SDL_free(pixel_buffer_a);
|
||||
SDL_free(pixel_buffer_b);
|
||||
|
||||
if (phdata->bitmap) {
|
||||
TRect aSource(TPoint(srcrect->x, srcrect->y), TSize(srcrect->w, srcrect->h));
|
||||
TPoint aDest(dstrect->x, dstrect->y);
|
||||
iRenderer->Gc()->BitBlt(aDest, phdata->bitmap, aSource);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CRenderer::CopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const NGAGE_CopyExData *copydata)
|
||||
{
|
||||
NGAGE_TextureData *phdata = (NGAGE_TextureData *)texture->internal;
|
||||
if (!phdata) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_FColor *c = &texture->color;
|
||||
int w = phdata->surface->w;
|
||||
int h = phdata->surface->h;
|
||||
int pitch = phdata->surface->pitch;
|
||||
void *source = phdata->surface->pixels;
|
||||
void *dest;
|
||||
|
||||
if (!source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *pixel_buffer_a = SDL_calloc(1, pitch * h);
|
||||
if (!pixel_buffer_a) {
|
||||
return false;
|
||||
}
|
||||
dest = pixel_buffer_a;
|
||||
|
||||
void *pixel_buffer_b = SDL_calloc(1, pitch * h);
|
||||
if (!pixel_buffer_a) {
|
||||
SDL_free(pixel_buffer_a);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (copydata->flip) {
|
||||
ApplyFlip(dest, source, pitch, w, h, copydata->flip);
|
||||
source = dest;
|
||||
}
|
||||
|
||||
if (copydata->scale_x != 1.f || copydata->scale_y != 1.f) {
|
||||
dest == pixel_buffer_a ? dest = pixel_buffer_b : dest = pixel_buffer_a;
|
||||
ApplyScale(dest, source, pitch, w, h, copydata->center.x, copydata->center.y, copydata->scale_x, copydata->scale_y);
|
||||
source = dest;
|
||||
}
|
||||
|
||||
if (copydata->angle) {
|
||||
dest == pixel_buffer_a ? dest = pixel_buffer_b : dest = pixel_buffer_a;
|
||||
ApplyRotation(dest, source, pitch, w, h, copydata->center.x, copydata->center.y, copydata->angle);
|
||||
source = dest;
|
||||
}
|
||||
|
||||
if (c->a != 1.f || c->r != 1.f || c->g != 1.f || c->b != 1.f) {
|
||||
dest == pixel_buffer_a ? dest = pixel_buffer_b : dest = pixel_buffer_a;
|
||||
ApplyColorMod(dest, source, pitch, w, h, texture->color);
|
||||
source = dest;
|
||||
}
|
||||
|
||||
Mem::Copy(phdata->bitmap->DataAddress(), source, pitch * h);
|
||||
SDL_free(pixel_buffer_a);
|
||||
SDL_free(pixel_buffer_b);
|
||||
|
||||
if (phdata->bitmap) {
|
||||
TRect aSource(TPoint(copydata->srcrect.x, copydata->srcrect.y), TSize(copydata->srcrect.w, copydata->srcrect.h));
|
||||
TPoint aDest(copydata->dstrect.x, copydata->dstrect.y);
|
||||
iRenderer->Gc()->BitBlt(aDest, phdata->bitmap, aSource);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CRenderer::CreateTextureData(NGAGE_TextureData *aTextureData, const TInt aWidth, const TInt aHeight)
|
||||
{
|
||||
if (!aTextureData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aTextureData->bitmap = new CFbsBitmap();
|
||||
if (!aTextureData->bitmap) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TInt error = aTextureData->bitmap->Create(TSize(aWidth, aHeight), EColor4K);
|
||||
if (error != KErrNone) {
|
||||
delete aTextureData->bitmap;
|
||||
aTextureData->bitmap = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CRenderer::DrawLines(NGAGE_Vertex *aVerts, const TInt aCount)
|
||||
{
|
||||
if (iRenderer && iRenderer->Gc()) {
|
||||
TPoint *aPoints = new TPoint[aCount];
|
||||
|
||||
for (TInt i = 0; i < aCount; i++) {
|
||||
aPoints[i] = TPoint(aVerts[i].x, aVerts[i].y);
|
||||
}
|
||||
|
||||
TUint32 aColor = (((TUint8)aVerts->color.a << 24) |
|
||||
((TUint8)aVerts->color.b << 16) |
|
||||
((TUint8)aVerts->color.g << 8) |
|
||||
(TUint8)aVerts->color.r);
|
||||
|
||||
iRenderer->Gc()->SetPenColor(aColor);
|
||||
iRenderer->Gc()->DrawPolyLineNoEndPoint(aPoints, aCount);
|
||||
|
||||
delete[] aPoints;
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::DrawPoints(NGAGE_Vertex *aVerts, const TInt aCount)
|
||||
{
|
||||
if (iRenderer && iRenderer->Gc()) {
|
||||
for (TInt i = 0; i < aCount; i++, aVerts++) {
|
||||
TUint32 aColor = (((TUint8)aVerts->color.a << 24) |
|
||||
((TUint8)aVerts->color.b << 16) |
|
||||
((TUint8)aVerts->color.g << 8) |
|
||||
(TUint8)aVerts->color.r);
|
||||
|
||||
iRenderer->Gc()->SetPenColor(aColor);
|
||||
iRenderer->Gc()->Plot(TPoint(aVerts->x, aVerts->y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::FillRects(NGAGE_Vertex *aVerts, const TInt aCount)
|
||||
{
|
||||
if (iRenderer && iRenderer->Gc()) {
|
||||
for (TInt i = 0; i < aCount; i++, aVerts++) {
|
||||
TPoint pos(aVerts[i].x, aVerts[i].y);
|
||||
TSize size(
|
||||
aVerts[i + 1].x,
|
||||
aVerts[i + 1].y);
|
||||
TRect rect(pos, size);
|
||||
|
||||
TUint32 aColor = (((TUint8)aVerts->color.a << 24) |
|
||||
((TUint8)aVerts->color.b << 16) |
|
||||
((TUint8)aVerts->color.g << 8) |
|
||||
(TUint8)aVerts->color.r);
|
||||
|
||||
iRenderer->Gc()->SetPenColor(aColor);
|
||||
iRenderer->Gc()->SetBrushColor(aColor);
|
||||
iRenderer->Gc()->DrawRect(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::Flip()
|
||||
{
|
||||
if (!iRenderer) {
|
||||
SDL_Log("iRenderer is NULL.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!iIsFocused) {
|
||||
return;
|
||||
}
|
||||
|
||||
iRenderer->Gc()->UseFont(iFont);
|
||||
|
||||
if (iShowFPS && iRenderer->Gc()) {
|
||||
UpdateFPS();
|
||||
|
||||
TBuf<64> info;
|
||||
|
||||
iRenderer->Gc()->SetPenStyle(CGraphicsContext::ESolidPen);
|
||||
iRenderer->Gc()->SetBrushStyle(CGraphicsContext::ENullBrush);
|
||||
iRenderer->Gc()->SetPenColor(KRgbCyan);
|
||||
|
||||
TRect aTextRect(TPoint(3, 203 - iFont->HeightInPixels()), TSize(45, iFont->HeightInPixels() + 2));
|
||||
iRenderer->Gc()->SetBrushStyle(CGraphicsContext::ESolidBrush);
|
||||
iRenderer->Gc()->SetBrushColor(KRgbBlack);
|
||||
iRenderer->Gc()->DrawRect(aTextRect);
|
||||
|
||||
// Draw messages.
|
||||
info.Format(_L("FPS: %d"), iFPS);
|
||||
iRenderer->Gc()->DrawText(info, TPoint(5, 203));
|
||||
} else {
|
||||
// This is a workaround that helps regulating the FPS.
|
||||
iRenderer->Gc()->DrawText(_L(""), TPoint(0, 0));
|
||||
}
|
||||
iRenderer->Gc()->DiscardFont();
|
||||
iRenderer->Flip(iDirectScreen);
|
||||
|
||||
// Keep the backlight on.
|
||||
if (iSuspendScreenSaver) {
|
||||
User::ResetInactivityTime();
|
||||
}
|
||||
// Suspend the current thread for a short while.
|
||||
// Give some time to other threads and active objects.
|
||||
User::After(0);
|
||||
}
|
||||
|
||||
void CRenderer::SetDrawColor(TUint32 iColor)
|
||||
{
|
||||
if (iRenderer && iRenderer->Gc()) {
|
||||
iRenderer->Gc()->SetPenColor(iColor);
|
||||
iRenderer->Gc()->SetBrushColor(iColor);
|
||||
iRenderer->Gc()->SetBrushStyle(CGraphicsContext::ESolidBrush);
|
||||
|
||||
TRAPD(err, iRenderer->SetCurrentColor(iColor));
|
||||
if (err != KErrNone) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::SetClipRect(TInt aX, TInt aY, TInt aWidth, TInt aHeight)
|
||||
{
|
||||
if (iRenderer && iRenderer->Gc()) {
|
||||
TRect viewportRect(aX, aY, aX + aWidth, aY + aHeight);
|
||||
iRenderer->Gc()->SetClippingRect(viewportRect);
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::UpdateFPS()
|
||||
{
|
||||
static TTime lastTime;
|
||||
static TInt frameCount = 0;
|
||||
TTime currentTime;
|
||||
const TUint KOneSecond = 1000000; // 1s in ms.
|
||||
|
||||
currentTime.HomeTime();
|
||||
++frameCount;
|
||||
|
||||
TTimeIntervalMicroSeconds timeDiff = currentTime.MicroSecondsFrom(lastTime);
|
||||
|
||||
if (timeDiff.Int64() >= KOneSecond) {
|
||||
// Calculate FPS.
|
||||
iFPS = frameCount;
|
||||
|
||||
// Reset frame count and last time.
|
||||
frameCount = 0;
|
||||
lastTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::SuspendScreenSaver(TBool aSuspend)
|
||||
{
|
||||
iSuspendScreenSaver = aSuspend;
|
||||
}
|
||||
|
||||
static SDL_Scancode ConvertScancode(int key)
|
||||
{
|
||||
SDL_Keycode keycode;
|
||||
|
||||
switch (key) {
|
||||
case EStdKeyBackspace: // Clear key
|
||||
keycode = SDLK_BACKSPACE;
|
||||
break;
|
||||
case 0x31: // 1
|
||||
keycode = SDLK_1;
|
||||
break;
|
||||
case 0x32: // 2
|
||||
keycode = SDLK_2;
|
||||
break;
|
||||
case 0x33: // 3
|
||||
keycode = SDLK_3;
|
||||
break;
|
||||
case 0x34: // 4
|
||||
keycode = SDLK_4;
|
||||
break;
|
||||
case 0x35: // 5
|
||||
keycode = SDLK_5;
|
||||
break;
|
||||
case 0x36: // 6
|
||||
keycode = SDLK_6;
|
||||
break;
|
||||
case 0x37: // 7
|
||||
keycode = SDLK_7;
|
||||
break;
|
||||
case 0x38: // 8
|
||||
keycode = SDLK_8;
|
||||
break;
|
||||
case 0x39: // 9
|
||||
keycode = SDLK_9;
|
||||
break;
|
||||
case 0x30: // 0
|
||||
keycode = SDLK_0;
|
||||
break;
|
||||
case 0x2a: // Asterisk
|
||||
keycode = SDLK_ASTERISK;
|
||||
break;
|
||||
case EStdKeyHash: // Hash
|
||||
keycode = SDLK_HASH;
|
||||
break;
|
||||
case EStdKeyDevice0: // Left softkey
|
||||
keycode = SDLK_SOFTLEFT;
|
||||
break;
|
||||
case EStdKeyDevice1: // Right softkey
|
||||
keycode = SDLK_SOFTRIGHT;
|
||||
break;
|
||||
case EStdKeyApplication0: // Call softkey
|
||||
keycode = SDLK_CALL;
|
||||
break;
|
||||
case EStdKeyApplication1: // End call softkey
|
||||
keycode = SDLK_ENDCALL;
|
||||
break;
|
||||
case EStdKeyDevice3: // Middle softkey
|
||||
keycode = SDLK_SELECT;
|
||||
break;
|
||||
case EStdKeyUpArrow: // Up arrow
|
||||
keycode = SDLK_UP;
|
||||
break;
|
||||
case EStdKeyDownArrow: // Down arrow
|
||||
keycode = SDLK_DOWN;
|
||||
break;
|
||||
case EStdKeyLeftArrow: // Left arrow
|
||||
keycode = SDLK_LEFT;
|
||||
break;
|
||||
case EStdKeyRightArrow: // Right arrow
|
||||
keycode = SDLK_RIGHT;
|
||||
break;
|
||||
default:
|
||||
keycode = SDLK_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return SDL_GetScancodeFromKey(keycode, NULL);
|
||||
}
|
||||
|
||||
void CRenderer::HandleEvent(const TWsEvent &aWsEvent)
|
||||
{
|
||||
Uint64 timestamp;
|
||||
|
||||
switch (aWsEvent.Type()) {
|
||||
case EEventKeyDown: /* Key events */
|
||||
timestamp = SDL_GetPerformanceCounter();
|
||||
SDL_SendKeyboardKey(timestamp, 1, aWsEvent.Key()->iCode, ConvertScancode(aWsEvent.Key()->iScanCode), true);
|
||||
|
||||
if (aWsEvent.Key()->iScanCode == EStdKeyHash) {
|
||||
if (iShowFPS) {
|
||||
iShowFPS = EFalse;
|
||||
} else {
|
||||
iShowFPS = ETrue;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case EEventKeyUp: /* Key events */
|
||||
timestamp = SDL_GetPerformanceCounter();
|
||||
SDL_SendKeyboardKey(timestamp, 1, aWsEvent.Key()->iCode, ConvertScancode(aWsEvent.Key()->iScanCode), false);
|
||||
|
||||
case EEventFocusGained:
|
||||
DisableKeyBlocking();
|
||||
if (!iDirectScreen->IsActive()) {
|
||||
TRAPD(err, iDirectScreen->StartL());
|
||||
if (KErrNone != err) {
|
||||
return;
|
||||
}
|
||||
iDirectScreen->ScreenDevice()->SetAutoUpdate(ETrue);
|
||||
iIsFocused = ETrue;
|
||||
}
|
||||
Flip();
|
||||
break;
|
||||
case EEventFocusLost:
|
||||
{
|
||||
if (iDirectScreen->IsActive()) {
|
||||
iDirectScreen->Cancel();
|
||||
}
|
||||
|
||||
iIsFocused = EFalse;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CRenderer::DisableKeyBlocking()
|
||||
{
|
||||
TRawEvent aEvent;
|
||||
|
||||
aEvent.Set((TRawEvent::TType) /*EDisableKeyBlock*/ 51);
|
||||
iWsSession.SimulateRawEvent(aEvent);
|
||||
}
|
||||
|
||||
void CRenderer::PumpEvents()
|
||||
{
|
||||
while (iWsEventStatus != KRequestPending) {
|
||||
iWsSession.GetEvent(iWsEvent);
|
||||
HandleEvent(iWsEvent);
|
||||
iWsEventStatus = KRequestPending;
|
||||
iWsSession.EventReady(&iWsEventStatus);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SDL_VIDEO_RENDER_NGAGE
|
||||
105
src/render/ngage/SDL_render_ngage_c.h
Normal file
105
src/render/ngage/SDL_render_ngage_c.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef ngage_video_render_ngage_c_h
|
||||
#define ngage_video_render_ngage_c_h
|
||||
|
||||
#define NGAGE_SCREEN_WIDTH 176
|
||||
#define NGAGE_SCREEN_HEIGHT 208
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../SDL_sysrender.h"
|
||||
|
||||
typedef struct NGAGE_RendererData
|
||||
{
|
||||
SDL_Rect *viewport;
|
||||
|
||||
} NGAGE_RendererData;
|
||||
|
||||
typedef struct NGAGE_Vertex
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
|
||||
struct
|
||||
{
|
||||
Uint8 a;
|
||||
Uint8 r;
|
||||
Uint8 g;
|
||||
Uint8 b;
|
||||
|
||||
} color;
|
||||
|
||||
} NGAGE_Vertex;
|
||||
|
||||
typedef struct CFbsBitmap CFbsBitmap;
|
||||
|
||||
typedef struct NGAGE_TextureData
|
||||
{
|
||||
CFbsBitmap *bitmap;
|
||||
SDL_Surface *surface;
|
||||
|
||||
} NGAGE_TextureData;
|
||||
|
||||
typedef struct NGAGE_CopyExData
|
||||
{
|
||||
SDL_Rect srcrect;
|
||||
SDL_Rect dstrect;
|
||||
|
||||
int angle;
|
||||
|
||||
struct
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
|
||||
} center;
|
||||
|
||||
SDL_FlipMode flip;
|
||||
|
||||
int scale_x;
|
||||
int scale_y;
|
||||
|
||||
} NGAGE_CopyExData;
|
||||
|
||||
void NGAGE_Clear(const Uint32 color);
|
||||
Uint32 NGAGE_ConvertColor(float r, float g, float b, float a, float color_scale);
|
||||
bool NGAGE_Copy(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Rect *srcrect, SDL_Rect *dstrect);
|
||||
bool NGAGE_CopyEx(SDL_Renderer *renderer, SDL_Texture *texture, NGAGE_CopyExData *copydata);
|
||||
bool NGAGE_CreateTextureData(NGAGE_TextureData *data, const int width, const int height);
|
||||
void NGAGE_DestroyTextureData(NGAGE_TextureData *data);
|
||||
void NGAGE_DrawLines(NGAGE_Vertex *verts, const int count);
|
||||
void NGAGE_DrawPoints(NGAGE_Vertex *verts, const int count);
|
||||
void NGAGE_FillRects(NGAGE_Vertex *verts, const int count);
|
||||
void NGAGE_Flip(void);
|
||||
void NGAGE_SetClipRect(const SDL_Rect *rect);
|
||||
void NGAGE_SetDrawColor(const Uint32 color);
|
||||
void NGAGE_PumpEventsInternal(void);
|
||||
void NGAGE_SuspendScreenSaverInternal(bool suspend);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ngage_video_render_ngage_c_h
|
||||
91
src/render/ngage/SDL_render_ngage_c.hpp
Normal file
91
src/render/ngage/SDL_render_ngage_c.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef ngage_video_render_ngage_c_hpp
|
||||
#define ngage_video_render_ngage_c_hpp
|
||||
|
||||
#include "SDL_render_ngage_c.h"
|
||||
#include <NRenderer.h>
|
||||
#include <e32std.h>
|
||||
#include <w32std.h>
|
||||
|
||||
class CRenderer : public MDirectScreenAccess
|
||||
{
|
||||
public:
|
||||
static CRenderer *NewL();
|
||||
virtual ~CRenderer();
|
||||
|
||||
// Rendering functions.
|
||||
void Clear(TUint32 iColor);
|
||||
bool Copy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect);
|
||||
bool CopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const NGAGE_CopyExData *copydata);
|
||||
bool CreateTextureData(NGAGE_TextureData *aTextureData, const TInt aWidth, const TInt aHeight);
|
||||
void DrawLines(NGAGE_Vertex *aVerts, const TInt aCount);
|
||||
void DrawPoints(NGAGE_Vertex *aVerts, const TInt aCount);
|
||||
void FillRects(NGAGE_Vertex *aVerts, const TInt aCount);
|
||||
void Flip();
|
||||
void SetDrawColor(TUint32 iColor);
|
||||
void SetClipRect(TInt aX, TInt aY, TInt aWidth, TInt aHeight);
|
||||
void UpdateFPS();
|
||||
void SuspendScreenSaver(TBool aSuspend);
|
||||
|
||||
// Event handling.
|
||||
void DisableKeyBlocking();
|
||||
void HandleEvent(const TWsEvent &aWsEvent);
|
||||
void PumpEvents();
|
||||
|
||||
private:
|
||||
CRenderer();
|
||||
void ConstructL(void);
|
||||
|
||||
// BackBuffer.
|
||||
CNRenderer *iRenderer;
|
||||
|
||||
// Direct screen access.
|
||||
CDirectScreenAccess *iDirectScreen;
|
||||
CFbsBitGc *iScreenGc;
|
||||
TBool iIsFocused;
|
||||
|
||||
// Window server session.
|
||||
RWsSession iWsSession;
|
||||
RWindowGroup iWsWindowGroup;
|
||||
TInt iWsWindowGroupID;
|
||||
RWindow iWsWindow;
|
||||
CWsScreenDevice *iWsScreen;
|
||||
|
||||
// Event handling.
|
||||
TRequestStatus iWsEventStatus;
|
||||
TWsEvent iWsEvent;
|
||||
|
||||
// MDirectScreenAccess functions.
|
||||
void Restart(RDirectScreenAccess::TTerminationReasons aReason);
|
||||
void AbortNow(RDirectScreenAccess::TTerminationReasons aReason);
|
||||
|
||||
// Frame per second.
|
||||
TBool iShowFPS;
|
||||
TUint iFPS;
|
||||
const CFont *iFont;
|
||||
|
||||
// Screen saver.
|
||||
TBool iSuspendScreenSaver;
|
||||
};
|
||||
|
||||
#endif // ngage_video_render_ngage_c_hpp
|
||||
152
src/render/ngage/SDL_render_ops.cpp
Normal file
152
src/render/ngage/SDL_render_ops.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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"
|
||||
|
||||
#include <3dtypes.h>
|
||||
#include "SDL_render_ops.hpp"
|
||||
|
||||
void ApplyColorMod(void *dest, void *source, int pitch, int width, int height, SDL_FColor color)
|
||||
{
|
||||
TUint16 *src_pixels = static_cast<TUint16 *>(source);
|
||||
TUint16 *dst_pixels = static_cast<TUint16 *>(dest);
|
||||
|
||||
TFixed rf = Real2Fix(color.r);
|
||||
TFixed gf = Real2Fix(color.g);
|
||||
TFixed bf = Real2Fix(color.b);
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
TUint16 pixel = src_pixels[y * pitch / 2 + x];
|
||||
TUint8 r = (pixel & 0xF800) >> 8;
|
||||
TUint8 g = (pixel & 0x07E0) >> 3;
|
||||
TUint8 b = (pixel & 0x001F) << 3;
|
||||
r = FixMul(r, rf);
|
||||
g = FixMul(g, gf);
|
||||
b = FixMul(b, bf);
|
||||
dst_pixels[y * pitch / 2 + x] = (r << 8) | (g << 3) | (b >> 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyFlip(void* dest, void* source, int pitch, int width, int height, SDL_FlipMode flip)
|
||||
{
|
||||
TUint16* src_pixels = static_cast<TUint16*>(source);
|
||||
TUint16* dst_pixels = static_cast<TUint16*>(dest);
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
int src_x = x;
|
||||
int src_y = y;
|
||||
|
||||
if (flip & SDL_FLIP_HORIZONTAL)
|
||||
{
|
||||
src_x = width - 1 - x;
|
||||
}
|
||||
|
||||
if (flip & SDL_FLIP_VERTICAL)
|
||||
{
|
||||
src_y = height - 1 - y;
|
||||
}
|
||||
|
||||
dst_pixels[y * pitch / 2 + x] = src_pixels[src_y * pitch / 2 + src_x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyRotation(void* dest, void* source, int pitch, int width, int height, TFixed center_x, TFixed center_y, TFixed angle)
|
||||
{
|
||||
TUint16* src_pixels = static_cast<TUint16*>(source);
|
||||
TUint16* dst_pixels = static_cast<TUint16*>(dest);
|
||||
|
||||
TFixed cos_angle = 0;
|
||||
TFixed sin_angle = 0;
|
||||
|
||||
if (angle != 0)
|
||||
{
|
||||
FixSinCos(angle, sin_angle, cos_angle);
|
||||
}
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
// Translate point to origin.
|
||||
TFixed translated_x = Int2Fix(x) - center_x;
|
||||
TFixed translated_y = Int2Fix(y) - center_y;
|
||||
|
||||
// Rotate point (clockwise).
|
||||
TFixed rotated_x = FixMul(translated_x, cos_angle) + FixMul(translated_y, sin_angle);
|
||||
TFixed rotated_y = FixMul(translated_y, cos_angle) - FixMul(translated_x, sin_angle);
|
||||
|
||||
// Translate point back.
|
||||
int final_x = Fix2Int(rotated_x + center_x);
|
||||
int final_y = Fix2Int(rotated_y + center_y);
|
||||
|
||||
// Check bounds.
|
||||
if (final_x >= 0 && final_x < width && final_y >= 0 && final_y < height)
|
||||
{
|
||||
dst_pixels[y * pitch / 2 + x] = src_pixels[final_y * pitch / 2 + final_x];
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_pixels[y * pitch / 2 + x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyScale(void* dest, void* source, int pitch, int width, int height, TFixed center_x, TFixed center_y, TFixed scale_x, TFixed scale_y)
|
||||
{
|
||||
TUint16* src_pixels = static_cast<TUint16*>(source);
|
||||
TUint16* dst_pixels = static_cast<TUint16*>(dest);
|
||||
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
for (int x = 0; x < width; ++x)
|
||||
{
|
||||
// Translate point to origin.
|
||||
TFixed translated_x = Int2Fix(x) - center_x;
|
||||
TFixed translated_y = Int2Fix(y) - center_y;
|
||||
|
||||
// Scale point.
|
||||
TFixed scaled_x = FixDiv(translated_x, scale_x);
|
||||
TFixed scaled_y = FixDiv(translated_y, scale_y);
|
||||
|
||||
// Translate point back.
|
||||
int final_x = Fix2Int(scaled_x + center_x);
|
||||
int final_y = Fix2Int(scaled_y + center_y);
|
||||
|
||||
// Check bounds.
|
||||
if (final_x >= 0 && final_x < width && final_y >= 0 && final_y < height)
|
||||
{
|
||||
dst_pixels[y * pitch / 2 + x] = src_pixels[final_y * pitch / 2 + final_x];
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_pixels[y * pitch / 2 + x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/render/ngage/SDL_render_ops.hpp
Normal file
32
src/render/ngage/SDL_render_ops.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef ngage_video_render_ops_hpp
|
||||
#define ngage_video_render_ops_hpp
|
||||
|
||||
#include <3dtypes.h>
|
||||
|
||||
void ApplyColorMod(void* dest, void* source, int pitch, int width, int height, SDL_FColor color);
|
||||
void ApplyFlip(void* dest, void* source, int pitch, int width, int height, SDL_FlipMode flip);
|
||||
void ApplyRotation(void* dest, void* source, int pitch, int width, int height, TFixed center_x, TFixed center_y, TFixed angle);
|
||||
void ApplyScale(void* dest, void* source, int pitch, int width, int height, TFixed center_x, TFixed center_y, TFixed scale_x, TFixed scale_y);
|
||||
|
||||
#endif // ngage_video_render_ops_hpp
|
||||
Reference in New Issue
Block a user