aboutsummaryrefslogtreecommitdiff
path: root/backends/graphics/dispmanxsdl
diff options
context:
space:
mode:
authorvanfanel2015-07-07 11:36:56 +0200
committervanfanel2015-07-20 17:15:04 +0200
commit6320a008ec27499b3174cd2ea8b3926a59f2e117 (patch)
tree0debf70e934e0e2159f48bd5da9b4f893ed19688 /backends/graphics/dispmanxsdl
parentbf68de9aa7c3131ffac65b15d5e971788c7fe9c9 (diff)
downloadscummvm-rg350-6320a008ec27499b3174cd2ea8b3926a59f2e117.tar.gz
scummvm-rg350-6320a008ec27499b3174cd2ea8b3926a59f2e117.tar.bz2
scummvm-rg350-6320a008ec27499b3174cd2ea8b3926a59f2e117.zip
SDL/DISPMANX: Updated rendering code for better buffers management.
Diffstat (limited to 'backends/graphics/dispmanxsdl')
-rw-r--r--backends/graphics/dispmanxsdl/dispmanxsdl-graphics.cpp445
-rw-r--r--backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h4
2 files changed, 245 insertions, 204 deletions
diff --git a/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.cpp b/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.cpp
index f2df0e0086..af48fce935 100644
--- a/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.cpp
+++ b/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.cpp
@@ -34,180 +34,277 @@
#include <bcm_host.h>
-#define NUMPAGES 2
-
struct dispvarsStruct {
DISPMANX_DISPLAY_HANDLE_T display;
- DISPMANX_MODEINFO_T amode;
DISPMANX_UPDATE_HANDLE_T update;
DISPMANX_ELEMENT_HANDLE_T element;
VC_IMAGE_TYPE_T pixFormat;
- VC_DISPMANX_ALPHA_T *alpha;
- VC_RECT_T srcRect;
- VC_RECT_T dstRect;
+ VC_DISPMANX_ALPHA_T alpha;
+
VC_RECT_T bmpRect;
- uint vcImagePtr;
- uint screen;
- uint pitch;
+ VC_RECT_T srcRect;
+ VC_RECT_T dstRect;
+ uint32_t vcImagePtr;
+ int screen;
+ int pitch;
+ unsigned int dispmanxWidth;
+ unsigned int dispmanxHeight;
bool aspectRatioCorrection;
void *pixmem;
-
+
+ int numpages;
struct dispmanxPage *pages;
- struct dispmanxPage *nextPage;
- bool pageflipPending;
+ struct dispmanxPage *currentPage;
+ int pageflipPending;
pthread_cond_t vsyncCondition;
+ pthread_mutex_t vsyncCondMutex;
pthread_mutex_t pendingMutex;
+
+ SDL_Surface *fscreen;
};
struct dispmanxPage {
- DISPMANX_RESOURCE_HANDLE_T resource;
+ DISPMANX_RESOURCE_HANDLE_T resource;
+ bool used;
+ // Each page has it's own mutex for
+ // isolating the access to it's "used" flag.
+ pthread_mutex_t pageUsedMutex;
+
+ // This field will allow us to access the
+ // main dispvars struct, for the vsync cb.
+ struct dispvarsStruct *dispvars;
};
DispmanXSdlGraphicsManager::DispmanXSdlGraphicsManager(SdlEventSource *sdlEventSource)
: SurfaceSdlGraphicsManager(sdlEventSource) {
- _dispvars = new dispvarsStruct;
+ _dispvars = new(dispvarsStruct);
DispmanXInit();
}
DispmanXSdlGraphicsManager::~DispmanXSdlGraphicsManager() {
DispmanXVideoQuit();
- delete _dispvars;
+ delete(_dispvars);
}
void DispmanXSdlGraphicsManager::DispmanXInit() {
_dispvars->screen = 0;
_dispvars->vcImagePtr = 0;
- _dispvars->pages = (struct dispmanxPage *)calloc(NUMPAGES, sizeof(struct dispmanxPage));
+ _dispvars->numpages = 3;
+ _dispvars->pages = (struct dispmanxPage *)calloc(_dispvars->numpages, sizeof(struct dispmanxPage));
_dispvars->pageflipPending = 0;
- _dispvars->nextPage = &_dispvars->pages[0];
+ _dispvars->currentPage = NULL;
+ _dispvars->pixFormat = VC_IMAGE_RGB565;
+
+ /* Transparency disabled */
+ _dispvars->alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
+ _dispvars->alpha.opacity = 255;
+ _dispvars->alpha.mask = 0;
+ _dispvars->element = 0;
+
+ // Init each page's variables
+ for (int i = 0; i < _dispvars->numpages; i++) {
+ _dispvars->pages[i].used = false;
+ _dispvars->pages[i].dispvars = _dispvars;
+ _dispvars->pages[i].resource = 0;
+ pthread_mutex_init(&_dispvars->pages[i].pageUsedMutex, NULL);
+ }
- // Initialize mutex and condition variable objects
- pthread_mutex_init(&_dispvars->pendingMutex, NULL);
+ // Initialize the other mutex and condition variables
pthread_cond_init(&_dispvars->vsyncCondition, NULL);
+ pthread_mutex_init(&_dispvars->pendingMutex, NULL);
+ pthread_mutex_init(&_dispvars->vsyncCondMutex, NULL);
// Before we call any vc_* function, we need to call this one.
bcm_host_init();
_dispvars->display = vc_dispmanx_display_open(_dispvars->screen);
-}
+ graphics_get_display_size(_dispvars->display, &_dispvars->dispmanxWidth, &_dispvars->dispmanxHeight);
-void DispmanXSdlGraphicsManager::DispmanXSetup(int width, int height, int bpp) {
- DispmanXFreeResources();
- vc_dispmanx_display_get_info(_dispvars->display, &_dispvars->amode);
+ // We need this so SDL_SetVideoMode() is called once.
+ _dispvars->fscreen = NULL;
+}
- _dispvars->pitch = width * (bpp / 8);
- _dispvars->pixFormat = VC_IMAGE_RGB565;
+void DispmanXSdlGraphicsManager::DispmanXSetup(int srcWidth, int srcHeight) {
+ unsigned int dstWidth, dstHeight, dstXpos, dstYpos;
- // Transparency disabled
- VC_DISPMANX_ALPHA_T layerAlpha;
- layerAlpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
- layerAlpha.opacity = 255;
- layerAlpha.mask = 0;
- _dispvars->alpha = &layerAlpha;
+ // If we have an element, we have to free it along with it's resources.
+ if (_dispvars->element) {
+ DispmanXFreeResources();
+ }
+ // We do this for 2 bytes per pixel which is default on the Rpi.
+ _dispvars->pitch = srcWidth * 2;
if (_dispvars->aspectRatioCorrection) {
- float orig_ratio = ((float)width / (float)height);
- int dst_width = _dispvars->amode.height * orig_ratio;
-
- // If we obtain an scaled image width that is bigger than the physical screen width,
- // then we keep the physical screen width as our maximun width.
- if (dst_width > _dispvars->amode.width)
- dst_width = _dispvars->amode.width;
- int dst_ypos = (_dispvars->amode.width - dst_width) / 2;
- vc_dispmanx_rect_set(&(_dispvars->dstRect), dst_ypos, 0,
- dst_width, _dispvars->amode.height);
+ float aspect = ((float)srcWidth / (float)srcHeight);
+ dstWidth = _dispvars->dispmanxHeight * aspect;
} else {
- vc_dispmanx_rect_set(&(_dispvars->dstRect), 0, 0,
- _dispvars->amode.width, _dispvars->amode.height);
+ dstWidth = _dispvars->dispmanxWidth;
+ }
+ dstHeight = _dispvars->dispmanxHeight;
+
+ // If we obtain a scaled image width that is bigger than the physical screen width,
+ // then we keep the physical screen width as our maximun width.
+ if (dstWidth > _dispvars->dispmanxWidth) {
+ dstWidth = _dispvars->dispmanxWidth;
}
- // We configure the rects now
- vc_dispmanx_rect_set(&(_dispvars->bmpRect), 0, 0, width, height);
- vc_dispmanx_rect_set(&(_dispvars->srcRect), 0, 0, width << 16, height << 16);
+ dstXpos = (_dispvars->dispmanxWidth - dstWidth) / 2;
+ dstYpos = (_dispvars->dispmanxHeight - dstHeight) / 2;
- for (int i = 0; i < NUMPAGES; i++)
- _dispvars->pages[i].resource = vc_dispmanx_resource_create(_dispvars->pixFormat, width, height,
- &(_dispvars->vcImagePtr));
-
- // Add element
+ // Remember we have to transfer the whole bitmap even if we would have
+ // interest in a part of it! Blitting is done by the GPU.
+ vc_dispmanx_rect_set(&_dispvars->dstRect, dstXpos, dstYpos, dstWidth, dstHeight);
+ vc_dispmanx_rect_set(&_dispvars->bmpRect, 0, 0, srcWidth, srcHeight);
+ vc_dispmanx_rect_set(&_dispvars->srcRect, 0, 0, srcWidth << 16, srcHeight << 16);
+
+ for (int i = 0; i < _dispvars->numpages; i++) {
+ _dispvars->pages[i].resource = vc_dispmanx_resource_create(_dispvars->pixFormat,
+ srcWidth, srcHeight, &(_dispvars->vcImagePtr));
+ }
+
+ // Add the element. Has to be removed before getting here again.
_dispvars->update = vc_dispmanx_update_start(0);
-
- _dispvars->element = vc_dispmanx_element_add(_dispvars->update, _dispvars->display, 0,
- &(_dispvars->dstRect), _dispvars->pages[0].resource, &(_dispvars->srcRect),
- DISPMANX_PROTECTION_NONE, _dispvars->alpha, 0, (DISPMANX_TRANSFORM_T)0);
-
- vc_dispmanx_update_submit_sync(_dispvars->update);
+
+ _dispvars->element = vc_dispmanx_element_add(
+ _dispvars->update,_dispvars->display, 0,
+ &_dispvars->dstRect, 0,
+ &_dispvars->srcRect, DISPMANX_PROTECTION_NONE,
+ &_dispvars->alpha, 0, (DISPMANX_TRANSFORM_T)0);
+
+ vc_dispmanx_update_submit_sync(_dispvars->update);
}
void DispmanXVSyncCallback (DISPMANX_UPDATE_HANDLE_T u, void *arg) {
- struct dispvarsStruct *_dispvars = (struct dispvarsStruct*)arg;
+ struct dispmanxPage *page = (struct dispmanxPage*)arg;
+ struct dispvarsStruct *dispvars = page->dispvars;
+
+ // Marking the page as free must be done before the signaling
+ // so when the update function continues (it won't continue until we signal)
+ // we can chose this page as free.
+ if (dispvars->currentPage) {
+ pthread_mutex_lock(&dispvars->currentPage->pageUsedMutex);
+
+ // We mark as free the page that was visible until now.
+ page->dispvars->currentPage->used = false;
+
+ pthread_mutex_unlock(&dispvars->currentPage->pageUsedMutex);
+ }
- // Changing the page to write must be done before the signaling
- // so we have the right page in nextPage when update_main continues
- if (_dispvars->nextPage == &_dispvars->pages[0])
- _dispvars->nextPage = &_dispvars->pages[1];
- else
- _dispvars->nextPage = &_dispvars->pages[0];
+ // The page on which we issued the flip that
+ // caused this callback becomes the visible one
+ dispvars->currentPage = page;
// These two things must be isolated "atomically" to avoid getting
- // a false positive in the pending_mutex test in update_main.
- pthread_mutex_lock(&_dispvars->pendingMutex);
-
- pthread_cond_signal(&_dispvars->vsyncCondition);
- _dispvars->pageflipPending = false;
-
- pthread_mutex_unlock(&_dispvars->pendingMutex);
-
+ // a false positive in the pending_mutex test in update function.
+ pthread_mutex_lock(&dispvars->pendingMutex);
+
+ dispvars->pageflipPending--;
+ pthread_cond_signal(&dispvars->vsyncCondition);
+
+ pthread_mutex_unlock(&dispvars->pendingMutex);
}
void DispmanXSdlGraphicsManager::DispmanXUpdate() {
+ // Wait until last issued flip completes to get a free page. Also,
+ // dispmanx doesn't support issuing more than one pageflip.
pthread_mutex_lock(&_dispvars->pendingMutex);
- if (_dispvars->pageflipPending) {
+ if (_dispvars->pageflipPending > 0) {
pthread_cond_wait(&_dispvars->vsyncCondition, &_dispvars->pendingMutex);
}
pthread_mutex_unlock(&_dispvars->pendingMutex);
+ struct dispmanxPage *page = DispmanXGetFreePage();
+
// Frame blitting
- vc_dispmanx_resource_write_data(_dispvars->nextPage->resource, _dispvars->pixFormat,
- _dispvars->pitch, _dispvars->pixmem, &(_dispvars->bmpRect));
+ vc_dispmanx_resource_write_data(page->resource, _dispvars->pixFormat,
+ _dispvars->pitch, _dispvars->pixmem, &_dispvars->bmpRect);
// Issue a page flip at the next vblank interval (will be done at vsync anyway).
_dispvars->update = vc_dispmanx_update_start(0);
vc_dispmanx_element_change_source(_dispvars->update, _dispvars->element,
- _dispvars->nextPage->resource);
- vc_dispmanx_update_submit(_dispvars->update, &DispmanXVSyncCallback, _dispvars);
+ page->resource);
+ vc_dispmanx_update_submit(_dispvars->update, &DispmanXVSyncCallback, page);
pthread_mutex_lock(&_dispvars->pendingMutex);
- _dispvars->pageflipPending = true;
+ _dispvars->pageflipPending++;
pthread_mutex_unlock(&_dispvars->pendingMutex);
}
+struct dispmanxPage *DispmanXSdlGraphicsManager::DispmanXGetFreePage(void) {
+ struct dispmanxPage *page = NULL;
+
+ while (!page)
+ {
+ // Try to find a free page
+ for (int i = 0; i < _dispvars->numpages; ++i) {
+ if (!_dispvars->pages[i].used)
+ {
+ page = (_dispvars->pages) + i;
+ break;
+ }
+ }
+
+ // If no page is free at the moment,
+ // wait until a free page is freed by vsync CB.
+ if (!page) {
+ pthread_mutex_lock(&_dispvars->vsyncCondMutex);
+ pthread_cond_wait(&_dispvars->vsyncCondition, &_dispvars->vsyncCondMutex);
+ pthread_mutex_unlock(&_dispvars->vsyncCondMutex);
+ }
+ }
+
+ // We mark the choosen page as used
+ pthread_mutex_lock(&page->pageUsedMutex);
+ page->used = true;
+ pthread_mutex_unlock(&page->pageUsedMutex);
+
+ return page;
+}
+
void DispmanXSdlGraphicsManager::DispmanXFreeResources(void) {
- _dispvars->update = vc_dispmanx_update_start(0);
-
- for (int i = 0; i < NUMPAGES; i++)
+ // What if we run into the vsync cb code after freeing the resources?
+ pthread_mutex_lock(&_dispvars->pendingMutex);
+ if (_dispvars->pageflipPending > 0)
+ {
+ pthread_cond_wait(&_dispvars->vsyncCondition, &_dispvars->pendingMutex);
+ }
+ pthread_mutex_unlock(&_dispvars->pendingMutex);
+
+ for (int i = 0; i < _dispvars->numpages; i++) {
vc_dispmanx_resource_delete(_dispvars->pages[i].resource);
-
+ _dispvars->pages[i].resource = 0;
+ _dispvars->pages[i].used = false;
+ }
+
+ _dispvars->update = vc_dispmanx_update_start(0);
vc_dispmanx_element_remove(_dispvars->update, _dispvars->element);
-
vc_dispmanx_update_submit_sync(_dispvars->update);
+ // We use this on the setup function to know if we have to free resources and element.
+ _dispvars->element = 0;
}
void DispmanXSdlGraphicsManager::DispmanXVideoQuit() {
+ // This also waits for pending flips to complete, that's needed before
+ // we destroy the mutexes and condition.
DispmanXFreeResources();
- // Close display and deinit
- vc_dispmanx_display_close(_dispvars->display);
- bcm_host_deinit();
-
- // Destroy mutexes and conditions
+
+ // Destroy the mutexes and conditions
+ for (int i = 0; i < _dispvars->numpages; i++) {
+ pthread_mutex_destroy(&_dispvars->pages[i].pageUsedMutex);
+ }
pthread_mutex_destroy(&_dispvars->pendingMutex);
+ pthread_mutex_destroy(&_dispvars->vsyncCondMutex);
pthread_cond_destroy(&_dispvars->vsyncCondition);
free(_dispvars->pages);
+
+ // Close display and deinit
+ vc_dispmanx_display_close(_dispvars->display);
+ bcm_host_deinit();
}
bool DispmanXSdlGraphicsManager::loadGFXMode() {
@@ -216,10 +313,10 @@ bool DispmanXSdlGraphicsManager::loadGFXMode() {
// In DispmanX, we manage aspect ratio correction, so for scummvm it's always disabled.
_videoMode.aspectRatioCorrection = false;
- _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
- _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
- _videoMode.hardwareHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
+ _videoMode.overlayWidth = _videoMode.screenWidth;
+ _videoMode.overlayHeight = _videoMode.screenHeight;
+ _videoMode.hardwareWidth = _videoMode.screenWidth;
+ _videoMode.hardwareHeight = _videoMode.screenHeight;
//
// Create the surface that contains the 8 bit game data
@@ -236,59 +333,30 @@ bool DispmanXSdlGraphicsManager::loadGFXMode() {
// Avoid having SDL_SRCALPHA set even if we supplied an alpha-channel in the format.
SDL_SetAlpha(_screen, 0, 255);
- // SDL 1.2 palettes default to all black,
- // SDL 1.3 palettes default to all white,
- // Thus set our own default palette to all black.
- // SDL_SetColors does nothing for non indexed surfaces.
+ // We set our own default palette to all black.
SDL_SetColors(_screen, _currentPalette, 0, 256);
//
// Create the surface that contains the scaled graphics in 16 bit mode
//
- // We call DispmanXSetup() before SDL_SetVideoMode() because we use _hwscreen == null
- // to know inside DispmanXSetup() if we've been there before and need to free resources.
- DispmanXSetup(_videoMode.screenWidth, _videoMode.screenHeight, 16);
- // _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16, SDL_FULLSCREEN);
+ DispmanXSetup(_videoMode.screenWidth, _videoMode.screenHeight);
+
_hwscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
0, 0, 0, 0);
-
- _dispvars->pixmem = _hwscreen->pixels;
-
- // We draw on a RAM surface, but we make this call just to get SDL input initialized.
- // Even if we don't use the returned SDL_Surface *, we still need to use the right dimensions
- // for mouse pointer adjustment to work correctly.
- SDL_SetVideoMode(_videoMode.screenWidth, _videoMode.screenHeight, 16, SDL_FULLSCREEN);
-
- detectSupportedFormats();
+ // This is just so SDL 1.x input is initialized. Only once!
+ if (_dispvars->fscreen == NULL)
+ _dispvars->fscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16, SDL_FULLSCREEN);
if (_hwscreen == NULL) {
- // DON'T use error(), as this tries to bring up the debug
- // console, which WON'T WORK now that _hwscreen is hosed.
-
- if (!_oldVideoMode.setup) {
- warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
- g_system->quit();
- } else {
- return false;
- }
+ // Don't use error here because we don't have access to the debug console
+ warning("Allocating surface for DispmanX rendering _hwscreen failed");
+ g_system->quit();
}
- //
- // Create the surface used for the graphics in 16 bit before scaling, and also the overlay
- //
-
- // Need some extra bytes around when using 2xSaI
- _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3,
- 16,
- _hwscreen->format->Rmask,
- _hwscreen->format->Gmask,
- _hwscreen->format->Bmask,
- _hwscreen->format->Amask);
-
- if (_tmpscreen == NULL)
- error("allocating _tmpscreen failed");
-
+ // We render to dispmanx resources from _hwscreen pixels array
+ _dispvars->pixmem = _hwscreen->pixels;
+
_overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight,
16,
_hwscreen->format->Rmask,
@@ -311,16 +379,6 @@ bool DispmanXSdlGraphicsManager::loadGFXMode() {
_overlayFormat.bShift = _overlayscreen->format->Bshift;
_overlayFormat.aShift = _overlayscreen->format->Ashift;
- _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3,
- 16,
- _hwscreen->format->Rmask,
- _hwscreen->format->Gmask,
- _hwscreen->format->Bmask,
- _hwscreen->format->Amask);
-
- if (_tmpscreen2 == NULL)
- error("allocating _tmpscreen2 failed");
-
#ifdef USE_OSD
_osdSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
_hwscreen->w,
@@ -336,29 +394,51 @@ bool DispmanXSdlGraphicsManager::loadGFXMode() {
#endif
_eventSource->resetKeyboadEmulation(
- _videoMode.screenWidth * _videoMode.scaleFactor - 1,
- effectiveScreenHeight() - 1);
-
- // Distinguish 555 and 565 mode
- if (_hwscreen->format->Rmask == 0x7C00)
- InitScalers(555);
- else
- InitScalers(565);
+ _videoMode.screenWidth, effectiveScreenHeight());
return true;
}
+void DispmanXSdlGraphicsManager::clearOverlay() {
+ //assert(_transactionMode == kTransactionNone);
+
+ Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
+
+ if (!_overlayVisible)
+ return;
+
+ // Clear the overlay by making the game screen "look through" everywhere.
+ SDL_Rect src, dst;
+ src.x = src.y = 0;
+ dst.x = dst.y = 0;
+ src.w = dst.w = _videoMode.screenWidth;
+ src.h = dst.h = _videoMode.screenHeight;
+ if (SDL_BlitSurface(_screen, &src, _hwscreen, &dst) != 0)
+ error("SDL_BlitSurface failed: %s", SDL_GetError());
+
+ SDL_LockSurface(_hwscreen);
+ SDL_LockSurface(_overlayscreen);
+ Normal1x((byte *)(_hwscreen->pixels), _hwscreen->pitch,
+ (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _videoMode.screenWidth, _videoMode.screenHeight);
+
+ SDL_UnlockSurface(_hwscreen);
+ SDL_UnlockSurface(_overlayscreen);
+
+ _forceFull = true;
+}
+
void DispmanXSdlGraphicsManager::internUpdateScreen() {
SDL_Surface *srcSurf, *origSurf;
int height, width;
- ScalerProc *scalerProc;
- int scale1;
// If the shake position changed, fill the dirty area with blackness
if (_currentShakePos != _newShakePos ||
(_mouseNeedsRedraw && _mouseBackup.y <= _currentShakePos)) {
SDL_Rect blackrect = {0, 0, (Uint16)(_videoMode.screenWidth * _videoMode.scaleFactor), (Uint16)(_newShakePos * _videoMode.scaleFactor)};
+ if (_videoMode.aspectRatioCorrection && !_overlayVisible)
+ blackrect.h = real2Aspect(blackrect.h - 1) + 1;
+
SDL_FillRect(_hwscreen, &blackrect, 0);
_currentShakePos = _newShakePos;
@@ -400,19 +480,14 @@ void DispmanXSdlGraphicsManager::internUpdateScreen() {
if (!_overlayVisible) {
origSurf = _screen;
- srcSurf = _tmpscreen;
+ srcSurf = _hwscreen;
width = _videoMode.screenWidth;
height = _videoMode.screenHeight;
- scalerProc = _scalerProc;
- scale1 = _videoMode.scaleFactor;
} else {
origSurf = _overlayscreen;
- srcSurf = _tmpscreen2;
+ srcSurf = _hwscreen;
width = _videoMode.overlayWidth;
height = _videoMode.overlayHeight;
- scalerProc = Normal1x;
-
- scale1 = 1;
}
// Add the area covered by the mouse cursor to the list of dirty rects if
@@ -433,50 +508,15 @@ void DispmanXSdlGraphicsManager::internUpdateScreen() {
if (_numDirtyRects > 0 || _mouseNeedsRedraw) {
SDL_Rect *r;
SDL_Rect dst;
- uint32 srcPitch, dstPitch;
SDL_Rect *lastRect = _dirtyRectList + _numDirtyRects;
for (r = _dirtyRectList; r != lastRect; ++r) {
dst = *r;
- dst.x++; // Shift rect by one since 2xSai needs to access the data around
- dst.y++; // any pixel to scale it, and we want to avoid mem access crashes.
if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0)
error("SDL_BlitSurface failed: %s", SDL_GetError());
}
- SDL_LockSurface(srcSurf);
- SDL_LockSurface(_hwscreen);
-
- srcPitch = srcSurf->pitch;
- dstPitch = _hwscreen->pitch;
-
- for (r = _dirtyRectList; r != lastRect; ++r) {
- register int dst_y = r->y + _currentShakePos;
- register int dst_h = 0;
- register int rx1 = r->x * scale1;
-
- if (dst_y < height) {
- dst_h = r->h;
- if (dst_h > height - dst_y)
- dst_h = height - dst_y;
-
- dst_y = dst_y * scale1;
-
- assert(scalerProc != NULL);
- scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,
- (byte *)_hwscreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h);
- }
-
- r->x = rx1;
- r->y = dst_y;
- r->w = r->w * scale1;
- r->h = dst_h * scale1;
-
- }
- SDL_UnlockSurface(srcSurf);
- SDL_UnlockSurface(_hwscreen);
-
// Readjust the dirty rect list in case we are doing a full update.
// This is necessary if shaking is active.
if (_forceFull) {
@@ -491,6 +531,7 @@ void DispmanXSdlGraphicsManager::internUpdateScreen() {
SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
}
#endif
+
// Finally, blit all our changes to the screen
if (!_displayDisabled) {
SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
@@ -531,15 +572,13 @@ void DispmanXSdlGraphicsManager::setFullscreenMode(bool enable) {
void DispmanXSdlGraphicsManager::setAspectRatioCorrection(bool enable) {
Common::StackLock lock(_graphicsMutex);
- // Ratio correction is managed externally by dispmanx, so we disable it at the SDL level but take note,
- // so it's effectively taken into account at the dispmanx level in DispmanXSetup().
- if (_oldVideoMode.setup && _dispvars->aspectRatioCorrection == enable)
- return;
+ // We simply take note on what's the aspect ratio correction activation state.
+ _dispvars->aspectRatioCorrection = enable;
- if (_transactionMode == kTransactionActive) {
- _dispvars->aspectRatioCorrection = enable;
- _transactionDetails.needHotswap = false;
- DispmanXSetup(_videoMode.screenWidth, _videoMode.screenHeight, 16);
+ // If we have a videomode setup already, call DispmanXSetup() again so aspect ratio
+ // correction activation/deactivation works from the menu.
+ if (_oldVideoMode.setup && _dispvars->aspectRatioCorrection == enable) {
+ DispmanXSetup(_videoMode.screenWidth, _videoMode.screenHeight);
}
}
diff --git a/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h b/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h
index a5abb8618a..c41f84ef7a 100644
--- a/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h
+++ b/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h
@@ -37,11 +37,13 @@ public:
bool handleScalerHotkeys(Common::KeyCode key);
void setFullscreenMode(bool enable);
void setAspectRatioCorrection(bool enable);
+ void clearOverlay();
protected:
// Raspberry Pi Dispmanx API
- void DispmanXSetup(int dwidth, int dheight, int dbpp);
+ void DispmanXSetup(int width, int height);
void DispmanXInit();
void DispmanXUpdate();
+ struct dispmanxPage *DispmanXGetFreePage();
void DispmanXFreeResources();
void DispmanXVideoQuit();
struct dispvarsStruct *_dispvars;