| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2026 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 "../../SDL_hints_c.h"
- #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, const int access)
- {
- return gRenderer->CreateTextureData(data, width, height, access);
- }
- void NGAGE_DestroyTextureData(NGAGE_TextureData *data)
- {
- if (data) {
- if (data->gc) {
- delete data->gc;
- data->gc = NULL;
- }
- if (data->device) {
- delete data->device;
- data->device = NULL;
- }
- if (data->mask_bitmap) {
- delete data->mask_bitmap;
- data->mask_bitmap = NULL;
- }
- delete data->bitmap;
- data->bitmap = NULL;
- }
- }
- void *NGAGE_GetBitmapDataAddress(NGAGE_TextureData *data)
- {
- if (!data || !data->bitmap) {
- return NULL;
- }
- return data->bitmap->DataAddress();
- }
- int NGAGE_GetBitmapScanLineLength(NGAGE_TextureData *data)
- {
- if (!data || !data->bitmap) {
- return 0;
- }
- return (int)CFbsBitmap::ScanLineLength(data->bitmap->SizeInPixels().iWidth, EColor4K);
- }
- 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_DrawGeometry(NGAGE_Vertex *verts, const int count)
- {
- gRenderer->DrawGeometry(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);
- }
- void NGAGE_SetRenderTargetInternal(NGAGE_TextureData *target)
- {
- if (gRenderer) {
- gRenderer->SetRenderTarget(target);
- }
- }
- static void SDLCALL NGAGE_ShowFPSChanged(void *userdata, const char *name, const char *oldValue, const char *newValue)
- {
- CRenderer *renderer = (CRenderer *)userdata;
- renderer->SetShowFPS(SDL_GetStringBoolean(newValue, false));
- }
- void *NGAGE_GetBackbufferAddress(void)
- {
- return gRenderer->GetCurrentBitmap()->DataAddress();
- }
- int NGAGE_GetBackbufferPitch(void)
- {
- return CFbsBitmap::ScanLineLength(NGAGE_SCREEN_WIDTH, EColor4K) / 2;
- }
- #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), iCurrentRenderTarget(0), iPixelBufferA(0), iPixelBufferB(0), iPixelBufferSize(0), iScratchBitmap(0), iMaskBitmap(0), iPointsBuffer(0), iPointsBufferSize(0) {}
- CRenderer::~CRenderer()
- {
- SDL_RemoveHintCallback(SDL_HINT_RENDER_NGAGE_SHOW_FPS, NGAGE_ShowFPSChanged, this);
- delete iRenderer;
- iRenderer = 0;
- SDL_free(iPixelBufferA);
- SDL_free(iPixelBufferB);
- delete iScratchBitmap;
- iScratchBitmap = 0;
- delete iMaskBitmap;
- iMaskBitmap = 0;
- delete[] iPointsBuffer;
- }
- 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);
- }
- SDL_AddHintCallback(SDL_HINT_RENDER_NGAGE_SHOW_FPS, NGAGE_ShowFPSChanged, this);
- }
- 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)
- {
- CFbsBitGc *gc = GetCurrentGc();
- if (gc) {
- gc->SetBrushColor(iColor);
- 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 || !phdata->bitmap) {
- return false;
- }
- SDL_FColor *c = &texture->color;
- const int bytes_per_pixel = 2;
- int sw = srcrect->w;
- int sh = srcrect->h;
- // Fast path: render target texture with no color mod.
- // BitBlt directly from its bitmap — DataAddress() is unreliable
- // for bitmaps that have been drawn into via a CFbsBitGc.
- bool no_color_mod = (c->a == 1.f && c->r == 1.f && c->g == 1.f && c->b == 1.f);
- float sx, sy;
- SDL_GetRenderScale(renderer, &sx, &sy);
- bool no_scale = (sx == 1.f && sy == 1.f);
- SDL_BlendMode blend;
- SDL_GetTextureBlendMode(texture, &blend);
- bool no_color_key = (blend != SDL_BLENDMODE_BLEND);
- if (phdata->gc && no_color_mod && no_scale && no_color_key) {
- CFbsBitGc *gc = GetCurrentGc();
- if (gc) {
- TRect aSource(TPoint(srcrect->x, srcrect->y), TSize(sw, sh));
- TPoint aDest(dstrect->x, dstrect->y);
- gc->BitBlt(aDest, phdata->bitmap, aSource);
- }
- return true;
- }
- // Fast path: color-key with no color mod and no scale.
- // Blit directly from the source bitmap into the destination, skipping transparent pixels.
- if (no_color_mod && no_scale && !no_color_key && phdata->has_color_key) {
- void *tex_data_ck = phdata->bitmap->DataAddress();
- CFbsBitmap *dst_bmp = GetCurrentBitmap();
- if (dst_bmp && tex_data_ck) {
- int tex_stride_ck = CFbsBitmap::ScanLineLength(phdata->bitmap->SizeInPixels().iWidth, EColor4K) / 2;
- TUint16 *src_base = static_cast<TUint16 *>(tex_data_ck) + srcrect->y * tex_stride_ck + srcrect->x;
- BlitWithAlphaKey(dst_bmp, dstrect->x, dstrect->y, src_base, sw, sh, tex_stride_ck);
- }
- return true;
- }
- int src_pitch = sw * bytes_per_pixel;
- int tex_pitch = CFbsBitmap::ScanLineLength(texture->w, EColor4K);
- void *tex_data = phdata->bitmap->DataAddress();
- if (!tex_data) {
- return false;
- }
- TInt required_size = src_pitch * sh;
- if (required_size > iPixelBufferSize) {
- void *new_buffer_a = SDL_realloc(iPixelBufferA, required_size);
- if (!new_buffer_a) {
- return false;
- }
- iPixelBufferA = new_buffer_a;
- void *new_buffer_b = SDL_realloc(iPixelBufferB, required_size);
- if (!new_buffer_b) {
- return false;
- }
- iPixelBufferB = new_buffer_b;
- iPixelBufferSize = required_size;
- }
- // Ensure scratch bitmap is allocated and large enough.
- if (!iScratchBitmap) {
- iScratchBitmap = new CFbsBitmap();
- if (!iScratchBitmap) {
- return false;
- }
- }
- TSize scratch_size = iScratchBitmap->SizeInPixels();
- if (scratch_size.iWidth < sw || scratch_size.iHeight < sh) {
- iScratchBitmap->Reset();
- TInt err = iScratchBitmap->Create(TSize(sw, sh), EColor4K);
- if (err != KErrNone) {
- return false;
- }
- }
- // Extract the srcrect region from the texture into buffer A.
- {
- TUint16 *tex_pixels = (TUint16 *)tex_data;
- TUint16 *buf_pixels = (TUint16 *)iPixelBufferA;
- int tex_pitch_u16 = tex_pitch / 2;
- for (int y = 0; y < sh; ++y) {
- TUint16 *src_row = tex_pixels + (srcrect->y + y) * tex_pitch_u16 + srcrect->x;
- TUint16 *dst_row = buf_pixels + y * sw;
- Mem::Copy(dst_row, src_row, src_pitch);
- }
- }
- void *source = iPixelBufferA;
- void *dest = iPixelBufferB;
- if (!no_color_mod) {
- ApplyColorMod(dest, source, src_pitch, sw, sh, texture->color);
- void *tmp = source;
- source = dest;
- dest = tmp;
- }
- if (!no_scale) {
- TFixed scale_x = Real2Fix(sx);
- TFixed scale_y = Real2Fix(sy);
- TFixed center_x = Int2Fix(sw / 2);
- TFixed center_y = Int2Fix(sh / 2);
- ApplyScale(dest, source, src_pitch, sw, sh, center_x, center_y, scale_x, scale_y);
- void *tmp = source;
- source = dest;
- dest = tmp;
- }
- // Copy result into scratch bitmap and blit from there.
- // The source texture is never modified.
- {
- TUint16 *scratch_pixels = (TUint16 *)iScratchBitmap->DataAddress();
- TUint16 *res_pixels = (TUint16 *)source;
- int scratch_pitch_u16 = CFbsBitmap::ScanLineLength(iScratchBitmap->SizeInPixels().iWidth, EColor4K) / 2;
- // Always copy all pixels into the scratch bitmap.
- for (int y = 0; y < sh; ++y) {
- TUint16 *dst_row = scratch_pixels + y * scratch_pitch_u16;
- TUint16 *src_row = res_pixels + y * sw;
- Mem::Copy(dst_row, src_row, src_pitch);
- }
- CFbsBitGc *gc = GetCurrentGc();
- if (gc) {
- TRect aSource(TPoint(0, 0), TSize(sw, sh));
- TPoint aDest(dstrect->x, dstrect->y);
- if (!no_color_key && phdata->has_color_key) {
- CFbsBitmap *dst_bmp = GetCurrentBitmap();
- if (dst_bmp) {
- BlitWithAlphaKey(dst_bmp, dstrect->x, dstrect->y, res_pixels, sw, sh, sw);
- }
- } else {
- gc->BitBlt(aDest, iScratchBitmap, 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 || !phdata->bitmap) {
- return false;
- }
- SDL_FColor *c = &texture->color;
- const int bytes_per_pixel = 2;
- int sw = copydata->srcrect.w;
- int sh = copydata->srcrect.h;
- int src_pitch = sw * bytes_per_pixel;
- int tex_pitch = CFbsBitmap::ScanLineLength(texture->w, EColor4K);
- void *tex_data = phdata->bitmap->DataAddress();
- if (!tex_data) {
- return false;
- }
- TInt required_size = src_pitch * sh;
- if (required_size > iPixelBufferSize) {
- void *new_buffer_a = SDL_realloc(iPixelBufferA, required_size);
- if (!new_buffer_a) {
- return false;
- }
- iPixelBufferA = new_buffer_a;
- void *new_buffer_b = SDL_realloc(iPixelBufferB, required_size);
- if (!new_buffer_b) {
- return false;
- }
- iPixelBufferB = new_buffer_b;
- iPixelBufferSize = required_size;
- }
- // Ensure scratch bitmap is allocated and large enough for the srcrect.
- if (!iScratchBitmap) {
- iScratchBitmap = new CFbsBitmap();
- if (!iScratchBitmap) {
- return false;
- }
- }
- TSize scratch_size = iScratchBitmap->SizeInPixels();
- if (scratch_size.iWidth < sw || scratch_size.iHeight < sh) {
- iScratchBitmap->Reset();
- TInt err = iScratchBitmap->Create(TSize(sw, sh), EColor4K);
- if (err != KErrNone) {
- return false;
- }
- }
- // Extract the srcrect region from the texture into buffer A.
- {
- TUint16 *tex_pixels = (TUint16 *)tex_data;
- TUint16 *buf_pixels = (TUint16 *)iPixelBufferA;
- int tex_pitch_u16 = tex_pitch / 2;
- for (int y = 0; y < sh; ++y) {
- TUint16 *src_row = tex_pixels + (copydata->srcrect.y + y) * tex_pitch_u16 + copydata->srcrect.x;
- TUint16 *dst_row = buf_pixels + y * sw;
- Mem::Copy(dst_row, src_row, src_pitch);
- }
- }
- void *source = iPixelBufferA;
- void *dest = iPixelBufferB;
- if (copydata->flip) {
- ApplyFlip(dest, source, src_pitch, sw, sh, copydata->flip);
- void *tmp = source;
- source = dest;
- dest = tmp;
- }
- if (copydata->scale_x != 1.f || copydata->scale_y != 1.f) {
- ApplyScale(dest, source, src_pitch, sw, sh, copydata->center.x, copydata->center.y, copydata->scale_x, copydata->scale_y);
- void *tmp = source;
- source = dest;
- dest = tmp;
- }
- if (copydata->angle) {
- ApplyRotation(dest, source, src_pitch, sw, sh, copydata->center.x, copydata->center.y, copydata->angle);
- void *tmp = source;
- source = dest;
- dest = tmp;
- }
- if (c->a != 1.f || c->r != 1.f || c->g != 1.f || c->b != 1.f) {
- ApplyColorMod(dest, source, src_pitch, sw, sh, texture->color);
- void *tmp = source;
- source = dest;
- dest = tmp;
- }
- // Copy the final result into the scratch bitmap and blit from there.
- // The source texture is never modified.
- {
- SDL_BlendMode blend;
- SDL_GetTextureBlendMode(texture, &blend);
- bool has_color_key = (blend == SDL_BLENDMODE_BLEND);
- TUint16 *scratch_pixels = (TUint16 *)iScratchBitmap->DataAddress();
- TUint16 *res_pixels = (TUint16 *)source;
- int scratch_pitch_u16 = CFbsBitmap::ScanLineLength(iScratchBitmap->SizeInPixels().iWidth, EColor4K) / 2;
- // Always copy all pixels into the scratch bitmap.
- for (int y = 0; y < sh; ++y) {
- TUint16 *dst_row = scratch_pixels + y * scratch_pitch_u16;
- TUint16 *src_row = res_pixels + y * sw;
- Mem::Copy(dst_row, src_row, src_pitch);
- }
- CFbsBitGc *gc = GetCurrentGc();
- if (gc) {
- TRect aSource(TPoint(0, 0), TSize(sw, sh));
- TPoint aDest(copydata->dstrect.x, copydata->dstrect.y);
- if (has_color_key && phdata->has_color_key) {
- CFbsBitmap *dst_bmp = GetCurrentBitmap();
- if (dst_bmp) {
- BlitWithAlphaKey(dst_bmp, copydata->dstrect.x, copydata->dstrect.y, res_pixels, sw, sh, sw);
- }
- } else {
- gc->BitBlt(aDest, iScratchBitmap, aSource);
- }
- }
- }
- return true;
- }
- bool CRenderer::CreateTextureData(NGAGE_TextureData *aTextureData, const TInt aWidth, const TInt aHeight, const TInt aAccess)
- {
- 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;
- }
- if (aAccess == SDL_TEXTUREACCESS_TARGET) {
- TRAPD(err1, aTextureData->device = CFbsBitmapDevice::NewL(aTextureData->bitmap));
- if (err1 != KErrNone || !aTextureData->device) {
- delete aTextureData->bitmap;
- aTextureData->bitmap = NULL;
- return false;
- }
- TRAPD(err2, aTextureData->gc = CFbsBitGc::NewL());
- if (err2 != KErrNone || !aTextureData->gc) {
- delete aTextureData->device;
- aTextureData->device = NULL;
- delete aTextureData->bitmap;
- aTextureData->bitmap = NULL;
- return false;
- }
- aTextureData->gc->Activate(aTextureData->device);
- } else {
- aTextureData->gc = NULL;
- aTextureData->device = NULL;
- }
- return true;
- }
- void CRenderer::DrawLines(NGAGE_Vertex *aVerts, const TInt aCount)
- {
- CFbsBitGc *gc = GetCurrentGc();
- if (gc) {
- gc->SetPenStyle(CGraphicsContext::ESolidPen);
- // Draw lines as pairs of points (start, end)
- for (TInt i = 0; i < aCount - 1; i += 2) {
- TPoint start(aVerts[i].x, aVerts[i].y);
- TPoint end(aVerts[i + 1].x, aVerts[i + 1].y);
- TRgb color = TRgb(aVerts[i].color.r, aVerts[i].color.g, aVerts[i].color.b);
- gc->SetPenColor(color);
- gc->DrawLine(start, end);
- }
- }
- }
- void CRenderer::DrawPoints(NGAGE_Vertex *aVerts, const TInt aCount)
- {
- CFbsBitGc *gc = GetCurrentGc();
- if (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);
- gc->SetPenColor(aColor);
- gc->Plot(TPoint(aVerts->x, aVerts->y));
- }
- }
- }
- // Gouraud-shaded triangle scanline fill directly into an EColor4K (XRGB4444) framebuffer.
- // Colors are interpolated per-scanline endpoint and per-pixel.
- static void FillTriangle(TUint16 *aPixels, TInt aStride,
- TInt aBmpW, TInt aBmpH,
- TInt aX0, TInt aY0, TInt aR0, TInt aG0, TInt aB0,
- TInt aX1, TInt aY1, TInt aR1, TInt aG1, TInt aB1,
- TInt aX2, TInt aY2, TInt aR2, TInt aG2, TInt aB2)
- {
- // Sort vertices by Y ascending (bubble sort on 3 elements).
- // Swap positions and colors together.
- #define SWAP3(ax, ay, ar, ag, ab, bx, by, br, bg, bb) \
- do { \
- TInt _t; \
- _t = ax; \
- ax = bx; \
- bx = _t; \
- _t = ay; \
- ay = by; \
- by = _t; \
- _t = ar; \
- ar = br; \
- br = _t; \
- _t = ag; \
- ag = bg; \
- bg = _t; \
- _t = ab; \
- ab = bb; \
- bb = _t; \
- } while (0)
- if (aY0 > aY1) {
- SWAP3(aX0, aY0, aR0, aG0, aB0, aX1, aY1, aR1, aG1, aB1);
- }
- if (aY1 > aY2) {
- SWAP3(aX1, aY1, aR1, aG1, aB1, aX2, aY2, aR2, aG2, aB2);
- }
- if (aY0 > aY1) {
- SWAP3(aX0, aY0, aR0, aG0, aB0, aX1, aY1, aR1, aG1, aB1);
- }
- #undef SWAP3
- TInt totalHeight = aY2 - aY0;
- if (totalHeight == 0) {
- return;
- }
- // Walk upper half [y0..y1] and lower half [y1..y2].
- for (TInt part = 0; part < 2; ++part) {
- TInt segHeight = (part == 0) ? (aY1 - aY0) : (aY2 - aY1);
- if (segHeight == 0) {
- continue;
- }
- TInt yStart = (part == 0) ? aY0 : aY1;
- TInt yEnd = (part == 0) ? aY1 : aY2;
- for (TInt y = yStart; y <= yEnd; ++y) {
- if (y < 0 || y >= aBmpH) {
- continue;
- }
- // 16.16 interpolation factors for long edge (v0->v2) and short edge.
- TInt tLong = ((y - aY0) << 16) / totalHeight;
- TInt tShort = ((y - yStart) << 16) / segHeight;
- // Interpolate X along both edges.
- TInt xLong = aX0 + (((aX2 - aX0) * tLong) >> 16);
- TInt xShort = (part == 0)
- ? aX0 + (((aX1 - aX0) * tShort) >> 16)
- : aX1 + (((aX2 - aX1) * tShort) >> 16);
- // Interpolate color along both edges (values 0-255).
- TInt rLong = aR0 + (((aR2 - aR0) * tLong) >> 16);
- TInt gLong = aG0 + (((aG2 - aG0) * tLong) >> 16);
- TInt bLong = aB0 + (((aB2 - aB0) * tLong) >> 16);
- TInt rShort, gShort, bShort;
- if (part == 0) {
- rShort = aR0 + (((aR1 - aR0) * tShort) >> 16);
- gShort = aG0 + (((aG1 - aG0) * tShort) >> 16);
- bShort = aB0 + (((aB1 - aB0) * tShort) >> 16);
- } else {
- rShort = aR1 + (((aR2 - aR1) * tShort) >> 16);
- gShort = aG1 + (((aG2 - aG1) * tShort) >> 16);
- bShort = aB1 + (((aB2 - aB1) * tShort) >> 16);
- }
- // Determine left/right endpoints and their colors.
- TInt xLeft, xRight;
- TInt rLeft, gLeft, bLeft;
- TInt rRight, gRight, bRight;
- if (xLong < xShort) {
- xLeft = xLong;
- xRight = xShort;
- rLeft = rLong;
- gLeft = gLong;
- bLeft = bLong;
- rRight = rShort;
- gRight = gShort;
- bRight = bShort;
- } else {
- xLeft = xShort;
- xRight = xLong;
- rLeft = rShort;
- gLeft = gShort;
- bLeft = bShort;
- rRight = rLong;
- gRight = gLong;
- bRight = bLong;
- }
- // Clamp X to bitmap width.
- if (xLeft < 0) {
- xLeft = 0;
- }
- if (xRight >= aBmpW) {
- xRight = aBmpW - 1;
- }
- TInt spanWidth = xRight - xLeft;
- TUint16 *row = aPixels + y * aStride;
- // Compute per-pixel color deltas once per span (one division each)
- // then step incrementally; avoids a division per pixel.
- if (spanWidth > 0) {
- TInt dr = ((rRight - rLeft) << 16) / spanWidth;
- TInt dg = ((gRight - gLeft) << 16) / spanWidth;
- TInt db = ((bRight - bLeft) << 16) / spanWidth;
- TInt r = rLeft << 16;
- TInt g = gLeft << 16;
- TInt b = bLeft << 16;
- for (TInt x = xLeft; x <= xRight; ++x) {
- // Pack to XRGB4444.
- row[x] = (TUint16)((((r >> 16) >> 4) << 8) | (((g >> 16) >> 4) << 4) | ((b >> 16) >> 4));
- r += dr;
- g += dg;
- b += db;
- }
- } else {
- row[xLeft] = (TUint16)(((rLeft >> 4) << 8) | ((gLeft >> 4) << 4) | (bLeft >> 4));
- }
- }
- }
- }
- void CRenderer::DrawGeometry(NGAGE_Vertex *aVerts, const TInt aCount)
- {
- if (aCount < 3) {
- return;
- }
- CFbsBitmap *bmp = GetCurrentBitmap();
- if (bmp) {
- TUint16 *pixels = reinterpret_cast<TUint16 *>(bmp->DataAddress());
- if (pixels) {
- TSize bmpSize = bmp->SizeInPixels();
- TInt stride = CFbsBitmap::ScanLineLength(bmpSize.iWidth, EColor4K) / 2;
- for (TInt i = 0; i + 2 < aCount; i += 3) {
- FillTriangle(pixels, stride,
- bmpSize.iWidth, bmpSize.iHeight,
- aVerts[i].x, aVerts[i].y,
- aVerts[i].color.r, aVerts[i].color.g, aVerts[i].color.b,
- aVerts[i + 1].x, aVerts[i + 1].y,
- aVerts[i + 1].color.r, aVerts[i + 1].color.g, aVerts[i + 1].color.b,
- aVerts[i + 2].x, aVerts[i + 2].y,
- aVerts[i + 2].color.r, aVerts[i + 2].color.g, aVerts[i + 2].color.b);
- }
- return;
- }
- }
- }
- void CRenderer::FillRects(NGAGE_Vertex *aVerts, const TInt aCount)
- {
- CFbsBitGc *gc = GetCurrentGc();
- if (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);
- gc->SetPenColor(aColor);
- gc->SetBrushColor(aColor);
- gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
- gc->SetPenStyle(CGraphicsContext::ENullPen);
- 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)
- {
- CFbsBitGc *gc = GetCurrentGc();
- if (gc) {
- gc->SetPenColor(iColor);
- gc->SetBrushColor(iColor);
- gc->SetBrushStyle(CGraphicsContext::ESolidBrush);
- }
- if (iRenderer) {
- TRAPD(err, iRenderer->SetCurrentColor(iColor));
- if (err != KErrNone) {
- return;
- }
- }
- }
- void CRenderer::SetClipRect(TInt aX, TInt aY, TInt aWidth, TInt aHeight)
- {
- CFbsBitGc *gc = GetCurrentGc();
- if (gc) {
- TRect viewportRect(aX, aY, aX + aWidth, aY + aHeight);
- 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;
- }
- void CRenderer::SetRenderTarget(NGAGE_TextureData *aTarget)
- {
- iCurrentRenderTarget = aTarget;
- }
- CFbsBitGc *CRenderer::GetCurrentGc()
- {
- if (iCurrentRenderTarget && iCurrentRenderTarget->gc) {
- return iCurrentRenderTarget->gc;
- }
- return iRenderer ? iRenderer->Gc() : NULL;
- }
- CFbsBitmap *CRenderer::GetCurrentBitmap()
- {
- if (iCurrentRenderTarget && iCurrentRenderTarget->bitmap) {
- return iCurrentRenderTarget->bitmap;
- }
- return iRenderer ? iRenderer->Bitmap() : NULL;
- }
- 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);
- break;
- case EEventKeyUp: /* Key events */
- timestamp = SDL_GetPerformanceCounter();
- SDL_SendKeyboardKey(timestamp, 1, aWsEvent.Key()->iCode, ConvertScancode(aWsEvent.Key()->iScanCode), false);
- break;
- 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
|