Atlas - SDL_render_ngage.c
Home / ext / SDL / src / render / ngage Lines: 1 | Size: 18813 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2026 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23#ifdef SDL_VIDEO_RENDER_NGAGE 24 25#ifndef M_PI 26#define M_PI 3.14159265358979323846 27#endif 28 29#ifndef Int2Fix 30#define Int2Fix(i) ((i) << 16) 31#endif 32 33#ifndef Fix2Int 34#define Fix2Int(i) ((((unsigned int)(i) > 0xFFFF0000) ? 0 : ((i) >> 16))) 35#endif 36 37#ifndef Fix2Real 38#define Fix2Real(i) ((i) / 65536.0) 39#endif 40 41#ifndef Real2Fix 42#define Real2Fix(i) ((int)((i) * 65536.0)) 43#endif 44 45#include "../SDL_sysrender.h" 46#include "SDL_render_ngage_c.h" 47 48static void NGAGE_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event); 49static bool NGAGE_GetOutputSize(SDL_Renderer *renderer, int *w, int *h); 50static bool NGAGE_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode); 51static bool NGAGE_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props); 52static bool NGAGE_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd); 53static bool NGAGE_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd); 54static bool NGAGE_QueueDrawVertices(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count); 55static bool NGAGE_QueueFillRects(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count); 56static bool NGAGE_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect); 57static 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); 58static 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); 59 60static void NGAGE_InvalidateCachedState(SDL_Renderer *renderer); 61static bool NGAGE_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize); 62static bool NGAGE_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch); 63 64static bool NGAGE_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch); 65static void NGAGE_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture); 66static bool NGAGE_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture); 67static SDL_Surface *NGAGE_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect); 68static bool NGAGE_RenderPresent(SDL_Renderer *renderer); 69static void NGAGE_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture); 70 71static void NGAGE_DestroyRenderer(SDL_Renderer *renderer); 72 73static bool NGAGE_SetVSync(SDL_Renderer *renderer, int vsync); 74 75static bool NGAGE_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props) 76{ 77 SDL_SetupRendererColorspace(renderer, create_props); 78 79 if (renderer->output_colorspace != SDL_COLORSPACE_RGB_DEFAULT) { 80 return SDL_SetError("Unsupported output colorspace"); 81 } 82 83 NGAGE_RendererData *phdata = SDL_calloc(1, sizeof(NGAGE_RendererData)); 84 if (!phdata) { 85 SDL_OutOfMemory(); 86 return false; 87 } 88 89 renderer->WindowEvent = NGAGE_WindowEvent; 90 renderer->GetOutputSize = NGAGE_GetOutputSize; 91 renderer->SupportsBlendMode = NGAGE_SupportsBlendMode; 92 renderer->CreateTexture = NGAGE_CreateTexture; 93 renderer->QueueSetViewport = NGAGE_QueueSetViewport; 94 renderer->QueueSetDrawColor = NGAGE_QueueSetDrawColor; 95 renderer->QueueDrawPoints = NGAGE_QueueDrawVertices; 96 renderer->QueueDrawLines = NGAGE_QueueDrawVertices; 97 renderer->QueueFillRects = NGAGE_QueueFillRects; 98 renderer->QueueCopy = NGAGE_QueueCopy; 99 renderer->QueueCopyEx = NGAGE_QueueCopyEx; 100 renderer->QueueGeometry = NGAGE_QueueGeometry; 101 renderer->InvalidateCachedState = NGAGE_InvalidateCachedState; 102 renderer->RunCommandQueue = NGAGE_RunCommandQueue; 103 renderer->UpdateTexture = NGAGE_UpdateTexture; 104 renderer->LockTexture = NGAGE_LockTexture; 105 renderer->UnlockTexture = NGAGE_UnlockTexture; 106 renderer->SetRenderTarget = NGAGE_SetRenderTarget; 107 renderer->RenderReadPixels = NGAGE_RenderReadPixels; 108 renderer->RenderPresent = NGAGE_RenderPresent; 109 renderer->DestroyTexture = NGAGE_DestroyTexture; 110 renderer->DestroyRenderer = NGAGE_DestroyRenderer; 111 renderer->SetVSync = NGAGE_SetVSync; 112 113 renderer->name = NGAGE_RenderDriver.name; 114 renderer->window = window; 115 renderer->internal = phdata; 116 renderer->npot_texture_wrap_unsupported = true; 117 118 SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB4444); 119 SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 1024); 120 SDL_SetHintWithPriority(SDL_HINT_RENDER_LINE_METHOD, "2", SDL_HINT_OVERRIDE); 121 122 return true; 123} 124 125SDL_RenderDriver NGAGE_RenderDriver = { 126 NGAGE_CreateRenderer, 127 "N-Gage" 128}; 129 130static void NGAGE_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event) 131{ 132 return; 133} 134 135static bool NGAGE_GetOutputSize(SDL_Renderer *renderer, int *w, int *h) 136{ 137 return true; 138} 139 140static bool NGAGE_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode) 141{ 142 switch (blendMode) { 143 case SDL_BLENDMODE_NONE: 144 case SDL_BLENDMODE_MOD: 145 return true; 146 default: 147 return false; 148 } 149} 150 151static bool NGAGE_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) 152{ 153 NGAGE_TextureData *data = (NGAGE_TextureData *)SDL_calloc(1, sizeof(*data)); 154 if (!data) { 155 return false; 156 } 157 158 if (!NGAGE_CreateTextureData(data, texture->w, texture->h, texture->access)) { 159 SDL_free(data); 160 return false; 161 } 162 163 texture->internal = data; 164 165 return true; 166} 167 168static bool NGAGE_QueueSetViewport(SDL_Renderer *renderer, SDL_RenderCommand *cmd) 169{ 170 if (!cmd->data.viewport.rect.w && !cmd->data.viewport.rect.h) { 171 SDL_Rect viewport = { 0, 0, NGAGE_SCREEN_WIDTH, NGAGE_SCREEN_HEIGHT }; 172 SDL_SetRenderViewport(renderer, &viewport); 173 } 174 175 return true; 176} 177 178static bool NGAGE_QueueSetDrawColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd) 179{ 180 return true; 181} 182 183static bool NGAGE_QueueDrawVertices(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count) 184{ 185 NGAGE_Vertex *verts = (NGAGE_Vertex *)SDL_AllocateRenderVertices(renderer, count * sizeof(NGAGE_Vertex), 0, &cmd->data.draw.first); 186 if (!verts) { 187 return false; 188 } 189 190 cmd->data.draw.count = count; 191 192 for (int i = 0; i < count; i++, points++) { 193 int fixed_x = Real2Fix(points->x); 194 int fixed_y = Real2Fix(points->y); 195 196 verts[i].x = Fix2Int(fixed_x); 197 verts[i].y = Fix2Int(fixed_y); 198 199 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); 200 201 verts[i].color.a = (Uint8)(color >> 24); 202 verts[i].color.b = (Uint8)(color >> 16); 203 verts[i].color.g = (Uint8)(color >> 8); 204 verts[i].color.r = (Uint8)color; 205 } 206 207 return true; 208} 209 210static bool NGAGE_QueueFillRects(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count) 211{ 212 NGAGE_Vertex *verts = (NGAGE_Vertex *)SDL_AllocateRenderVertices(renderer, count * 2 * sizeof(NGAGE_Vertex), 0, &cmd->data.draw.first); 213 if (!verts) { 214 return false; 215 } 216 217 cmd->data.draw.count = count; 218 219 for (int i = 0; i < count; i++, rects++) { 220 verts[i * 2].x = Real2Fix(rects->x); 221 verts[i * 2].y = Real2Fix(rects->y); 222 verts[i * 2 + 1].x = Real2Fix(rects->w); 223 verts[i * 2 + 1].y = Real2Fix(rects->h); 224 225 verts[i * 2].x = Fix2Int(verts[i * 2].x); 226 verts[i * 2].y = Fix2Int(verts[i * 2].y); 227 verts[i * 2 + 1].x = Fix2Int(verts[i * 2 + 1].x); 228 verts[i * 2 + 1].y = Fix2Int(verts[i * 2 + 1].y); 229 230 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); 231 232 verts[i * 2].color.a = (Uint8)(color >> 24); 233 verts[i * 2].color.b = (Uint8)(color >> 16); 234 verts[i * 2].color.g = (Uint8)(color >> 8); 235 verts[i * 2].color.r = (Uint8)color; 236 } 237 238 return true; 239} 240 241static bool NGAGE_QueueCopy(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect) 242{ 243 SDL_Rect *verts = (SDL_Rect *)SDL_AllocateRenderVertices(renderer, 2 * sizeof(SDL_Rect), 0, &cmd->data.draw.first); 244 245 if (!verts) { 246 return false; 247 } 248 249 cmd->data.draw.count = 1; 250 251 verts->x = (int)srcrect->x; 252 verts->y = (int)srcrect->y; 253 verts->w = (int)srcrect->w; 254 verts->h = (int)srcrect->h; 255 256 verts++; 257 258 verts->x = (int)dstrect->x; 259 verts->y = (int)dstrect->y; 260 verts->w = (int)dstrect->w; 261 verts->h = (int)dstrect->h; 262 263 return true; 264} 265 266static 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) 267{ 268 NGAGE_CopyExData *verts = (NGAGE_CopyExData *)SDL_AllocateRenderVertices(renderer, sizeof(NGAGE_CopyExData), 0, &cmd->data.draw.first); 269 270 if (!verts) { 271 return false; 272 } 273 274 cmd->data.draw.count = 1; 275 276 verts->srcrect.x = (int)srcquad->x; 277 verts->srcrect.y = (int)srcquad->y; 278 verts->srcrect.w = (int)srcquad->w; 279 verts->srcrect.h = (int)srcquad->h; 280 verts->dstrect.x = (int)dstrect->x; 281 verts->dstrect.y = (int)dstrect->y; 282 verts->dstrect.w = (int)dstrect->w; 283 verts->dstrect.h = (int)dstrect->h; 284 285 verts->angle = Real2Fix(angle); 286 // Convert center from destination-space to source-space. 287 // Center is relative to dstrect, but rotation is applied in source texture space. 288 float center_x_src = (center->x / dstrect->w) * srcquad->w; 289 float center_y_src = (center->y / dstrect->h) * srcquad->h; 290 verts->center.x = Real2Fix(center_x_src); 291 verts->center.y = Real2Fix(center_y_src); 292 verts->scale_x = Real2Fix(scale_x); 293 verts->scale_y = Real2Fix(scale_y); 294 295 verts->flip = flip; 296 297 return true; 298} 299 300static 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) 301{ 302 return true; 303} 304 305static void NGAGE_InvalidateCachedState(SDL_Renderer *renderer) 306{ 307 return; 308} 309 310static bool NGAGE_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) 311{ 312 NGAGE_RendererData *phdata = (NGAGE_RendererData *)renderer->internal; 313 if (!phdata) { 314 return false; 315 } 316 phdata->viewport = 0; 317 318 while (cmd) { 319 switch (cmd->command) { 320 case SDL_RENDERCMD_NO_OP: 321 break; 322 case SDL_RENDERCMD_SETVIEWPORT: 323 phdata->viewport = &cmd->data.viewport.rect; 324 break; 325 326 case SDL_RENDERCMD_SETCLIPRECT: 327 { 328 const SDL_Rect *rect = &cmd->data.cliprect.rect; 329 330 if (cmd->data.cliprect.enabled) { 331 NGAGE_SetClipRect(rect); 332 } 333 334 break; 335 } 336 337 case SDL_RENDERCMD_SETDRAWCOLOR: 338 { 339 break; 340 } 341 342 case SDL_RENDERCMD_CLEAR: 343 { 344 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); 345 346 NGAGE_Clear(color); 347 break; 348 } 349 350 case SDL_RENDERCMD_DRAW_POINTS: 351 { 352 NGAGE_Vertex *verts = (NGAGE_Vertex *)(((Uint8 *)vertices) + cmd->data.draw.first); 353 const int count = cmd->data.draw.count; 354 355 // Apply viewport. 356 if (phdata->viewport && (phdata->viewport->x || phdata->viewport->y)) { 357 for (int i = 0; i < count; i++) { 358 verts[i].x += phdata->viewport->x; 359 verts[i].y += phdata->viewport->y; 360 } 361 } 362 363 NGAGE_DrawPoints(verts, count); 364 break; 365 } 366 case SDL_RENDERCMD_DRAW_LINES: 367 { 368 NGAGE_Vertex *verts = (NGAGE_Vertex *)(((Uint8 *)vertices) + cmd->data.draw.first); 369 const int count = cmd->data.draw.count; 370 371 // Apply viewport. 372 if (phdata->viewport && (phdata->viewport->x || phdata->viewport->y)) { 373 for (int i = 0; i < count; i++) { 374 verts[i].x += phdata->viewport->x; 375 verts[i].y += phdata->viewport->y; 376 } 377 } 378 379 NGAGE_DrawLines(verts, count); 380 break; 381 } 382 383 case SDL_RENDERCMD_FILL_RECTS: 384 { 385 NGAGE_Vertex *verts = (NGAGE_Vertex *)(((Uint8 *)vertices) + cmd->data.draw.first); 386 const int count = cmd->data.draw.count; 387 388 // Apply viewport. 389 if (phdata->viewport && (phdata->viewport->x || phdata->viewport->y)) { 390 for (int i = 0; i < count; i++) { 391 verts[i].x += phdata->viewport->x; 392 verts[i].y += phdata->viewport->y; 393 } 394 } 395 396 NGAGE_FillRects(verts, count); 397 break; 398 } 399 400 case SDL_RENDERCMD_COPY: 401 { 402 SDL_Rect *verts = (SDL_Rect *)(((Uint8 *)vertices) + cmd->data.draw.first); 403 SDL_Rect *srcrect = verts; 404 SDL_Rect *dstrect = verts + 1; 405 SDL_Texture *texture = cmd->data.draw.texture; 406 407 // Apply viewport. 408 if (phdata->viewport && (phdata->viewport->x || phdata->viewport->y)) { 409 dstrect->x += phdata->viewport->x; 410 dstrect->y += phdata->viewport->y; 411 } 412 413 NGAGE_Copy(renderer, texture, srcrect, dstrect); 414 break; 415 } 416 417 case SDL_RENDERCMD_COPY_EX: 418 { 419 NGAGE_CopyExData *copydata = (NGAGE_CopyExData *)(((Uint8 *)vertices) + cmd->data.draw.first); 420 SDL_Texture *texture = cmd->data.draw.texture; 421 422 // Apply viewport. 423 if (phdata->viewport && (phdata->viewport->x || phdata->viewport->y)) { 424 copydata->dstrect.x += phdata->viewport->x; 425 copydata->dstrect.y += phdata->viewport->y; 426 } 427 428 NGAGE_CopyEx(renderer, texture, copydata); 429 break; 430 } 431 432 case SDL_RENDERCMD_GEOMETRY: 433 { 434 break; 435 } 436 } 437 cmd = cmd->next; 438 } 439 440 return true; 441} 442 443static bool NGAGE_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch) 444{ 445 NGAGE_TextureData *phdata = (NGAGE_TextureData *)texture->internal; 446 447 if (!phdata) { 448 return false; 449 } 450 451 Uint8 *dst = (Uint8 *)NGAGE_GetBitmapDataAddress(phdata); 452 if (!dst) { 453 return false; 454 } 455 456 const int bytes_per_pixel = 2; 457 const int bitmap_pitch = texture->w * bytes_per_pixel; 458 459 const Uint8 *src = (const Uint8 *)pixels; 460 dst += rect->y * bitmap_pitch + rect->x * bytes_per_pixel; 461 462 const size_t length = (size_t)rect->w * bytes_per_pixel; 463 for (int row = 0; row < rect->h; ++row) { 464 SDL_memcpy(dst, src, length); 465 src += pitch; 466 dst += bitmap_pitch; 467 } 468 469 return true; 470} 471 472static bool NGAGE_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch) 473{ 474 NGAGE_TextureData *phdata = (NGAGE_TextureData *)texture->internal; 475 476 if (!phdata) { 477 return false; 478 } 479 480 Uint8 *data = (Uint8 *)NGAGE_GetBitmapDataAddress(phdata); 481 if (!data) { 482 return false; 483 } 484 485 const int bytes_per_pixel = 2; 486 const int bitmap_pitch = texture->w * bytes_per_pixel; 487 488 *pixels = (void *)(data + rect->y * bitmap_pitch + rect->x * bytes_per_pixel); 489 *pitch = bitmap_pitch; 490 return true; 491} 492 493static void NGAGE_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) 494{ 495} 496 497static bool NGAGE_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) 498{ 499 NGAGE_RendererData *data = (NGAGE_RendererData *)renderer->internal; 500 501 if (texture) { 502 NGAGE_TextureData *texturedata = (NGAGE_TextureData *)texture->internal; 503 if (!texturedata || !texturedata->gc) { 504 return SDL_SetError("Texture is not a render target"); 505 } 506 data->current_target = texture; 507 NGAGE_SetRenderTargetInternal(texturedata); 508 } else { 509 data->current_target = NULL; 510 NGAGE_SetRenderTargetInternal(NULL); 511 } 512 513 return true; 514} 515 516static SDL_Surface *NGAGE_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) 517{ 518 return (SDL_Surface *)0; 519} 520 521static bool NGAGE_RenderPresent(SDL_Renderer *renderer) 522{ 523 NGAGE_Flip(); 524 525 return true; 526} 527 528static void NGAGE_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) 529{ 530 NGAGE_TextureData *data = (NGAGE_TextureData *)texture->internal; 531 if (data) { 532 NGAGE_DestroyTextureData(data); 533 SDL_free(data); 534 texture->internal = 0; 535 } 536} 537 538static void NGAGE_DestroyRenderer(SDL_Renderer *renderer) 539{ 540 NGAGE_RendererData *phdata = (NGAGE_RendererData *)renderer->internal; 541 if (phdata) { 542 SDL_free(phdata); 543 renderer->internal = 0; 544 } 545} 546 547static bool NGAGE_SetVSync(SDL_Renderer *renderer, int vsync) 548{ 549 return true; 550} 551 552#endif // SDL_VIDEO_RENDER_NGAGE 553[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.