From d8a61120497bc2d7bd5c6a562386571f4e195b27 Mon Sep 17 00:00:00 2001 From: rogerman Date: Sat, 19 Mar 2016 02:22:03 +0000 Subject: [PATCH] GPU: - The framebuffer pointers in NDSDisplayInfo are no longer assumed to be 16-bits per pixel in size. This is being done now in preparation for higher color depth processing. (This feature is not yet implemented.) - Instead, clients should be reading NDSDisplayInfo.colorFormat to determine the color format of the framebuffers. NDSDisplayInfo.pixelBytes is a convenience field that reports the number of bytes per pixel (either 2 or 4 bytes). - By default, the framebuffers will continue to be in 16-bit BGR555_Rev format for backwards compatibility. --- desmume/src/GPU.cpp | 227 ++++++++++++------ desmume/src/GPU.h | 81 ++++++- desmume/src/cli/main.cpp | 4 +- desmume/src/cocoa/OGLDisplayOutput.cpp | 56 +++-- desmume/src/cocoa/OGLDisplayOutput.h | 10 +- desmume/src/cocoa/cocoa_output.h | 25 +- desmume/src/cocoa/cocoa_output.mm | 72 ++++-- .../userinterface/DisplayWindowController.mm | 22 +- desmume/src/cocoa/utilities.c | 52 ++++ desmume/src/cocoa/utilities.h | 2 + desmume/src/gfx3d.h | 1 + desmume/src/gtk-glade/callbacks.cpp | 2 +- desmume/src/gtk-glade/callbacks_IO.cpp | 2 +- desmume/src/gtk/main.cpp | 6 +- desmume/src/qt/project/frontend/video.cpp | 2 +- desmume/src/windows/aviout.cpp | 2 +- desmume/src/windows/hotkey.cpp | 8 +- 17 files changed, 407 insertions(+), 167 deletions(-) diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index accee0106..f43244b5b 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -4010,8 +4010,8 @@ void GPUEngineBase::SetDisplayByID(const NDSDisplayID theDisplayID) { const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); this->_targetDisplayID = theDisplayID; - this->nativeBuffer = dispInfo.nativeBuffer[theDisplayID]; - this->customBuffer = dispInfo.customBuffer[theDisplayID]; + this->nativeBuffer = (u16 *)dispInfo.nativeBuffer[theDisplayID]; + this->customBuffer = (u16 *)dispInfo.customBuffer[theDisplayID]; } GPUEngineID GPUEngineBase::GetEngineID() const @@ -4033,8 +4033,8 @@ void GPUEngineBase::SetCustomFramebufferSize(size_t w, size_t h) this->_internalRenderLineTargetCustom = newWorkingScanline; this->_renderLineLayerIDCustom = newBGPixels; - this->nativeBuffer = GPU->GetDisplayInfo().nativeBuffer[this->_targetDisplayID]; - this->customBuffer = GPU->GetDisplayInfo().customBuffer[this->_targetDisplayID]; + this->nativeBuffer = (u16 *)GPU->GetDisplayInfo().nativeBuffer[this->_targetDisplayID]; + this->customBuffer = (u16 *)GPU->GetDisplayInfo().customBuffer[this->_targetDisplayID]; this->_bgLayerIndexCustom = newBGLayerIndexCustom; this->_bgLayerColorCustom = newBGLayerColorCustom; @@ -5700,17 +5700,19 @@ GPUSubsystem::GPUSubsystem() _customVRAMBlank = NULL; _customFramebuffer = (u16 *)malloc_alignedCacheLine(GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(u16) * 2); + _displayInfo.colorFormat = NDSColorFormat_BGR555_Rev; + _displayInfo.pixelBytes = sizeof(u16); _displayInfo.isCustomSizeRequested = false; _displayInfo.customWidth = GPU_FRAMEBUFFER_NATIVE_WIDTH; _displayInfo.customHeight = GPU_FRAMEBUFFER_NATIVE_HEIGHT; _displayInfo.masterNativeBuffer = _nativeFramebuffer; _displayInfo.nativeBuffer[NDSDisplayID_Main] = _displayInfo.masterNativeBuffer; - _displayInfo.nativeBuffer[NDSDisplayID_Touch] = _displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); + _displayInfo.nativeBuffer[NDSDisplayID_Touch] = (u8 *)_displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * _displayInfo.pixelBytes); _displayInfo.masterCustomBuffer = _customFramebuffer; _displayInfo.customBuffer[NDSDisplayID_Main] = _displayInfo.masterCustomBuffer; - _displayInfo.customBuffer[NDSDisplayID_Touch] = _displayInfo.masterCustomBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); + _displayInfo.customBuffer[NDSDisplayID_Touch] = (u8 *)_displayInfo.masterCustomBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * _displayInfo.pixelBytes); _displayInfo.didPerformCustomRender[NDSDisplayID_Main] = false; _displayInfo.didPerformCustomRender[NDSDisplayID_Touch] = false; @@ -5788,8 +5790,8 @@ void GPUSubsystem::Reset() this->_displayInfo.renderedBuffer[NDSDisplayID_Main] = this->_displayInfo.nativeBuffer[NDSDisplayID_Main]; this->_displayInfo.didPerformCustomRender[NDSDisplayID_Touch] = false; - this->_displayInfo.nativeBuffer[NDSDisplayID_Touch] = this->_displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); - this->_displayInfo.customBuffer[NDSDisplayID_Touch] = this->_displayInfo.masterCustomBuffer + (this->_displayInfo.customWidth * this->_displayInfo.customHeight); + this->_displayInfo.nativeBuffer[NDSDisplayID_Touch] = (u8 *)this->_displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * this->_displayInfo.pixelBytes); + this->_displayInfo.customBuffer[NDSDisplayID_Touch] = (u8 *)this->_displayInfo.masterCustomBuffer + (this->_displayInfo.customWidth * this->_displayInfo.customHeight * this->_displayInfo.pixelBytes); this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = GPU_FRAMEBUFFER_NATIVE_WIDTH; this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = GPU_FRAMEBUFFER_NATIVE_HEIGHT; this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = this->_displayInfo.nativeBuffer[NDSDisplayID_Touch]; @@ -5942,7 +5944,7 @@ size_t GPUSubsystem::GetCustomFramebufferHeight() const return this->_displayInfo.customHeight; } -void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, u16 *clientNativeBuffer, u16 *clientCustomBuffer) +void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, void *clientNativeBuffer, void *clientCustomBuffer) { if (w < GPU_FRAMEBUFFER_NATIVE_WIDTH || h < GPU_FRAMEBUFFER_NATIVE_HEIGHT) { @@ -5955,11 +5957,9 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, u16 *clientNativ const float customHeightScale = (float)h / (float)GPU_FRAMEBUFFER_NATIVE_HEIGHT; const float newGpuLargestDstLineCount = (size_t)ceilf(customHeightScale); - u16 *oldCustomFramebuffer = this->_customFramebuffer; u16 *oldGpuDstToSrcIndexPtr = _gpuDstToSrcIndex; u8 *oldGpuDstToSrcSSSE3_u8 = _gpuDstToSrcSSSE3_u8; u8 *oldGpuDstToSrcSSSE3_u16 = _gpuDstToSrcSSSE3_u16; - u16 *oldCustomVRAM = this->_customVRAM; for (size_t srcX = 0, currentPitchCount = 0; srcX < GPU_FRAMEBUFFER_NATIVE_WIDTH; srcX++) { @@ -6024,12 +6024,94 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, u16 *clientNativ newGpuDstToSrcSSSE3_u16[(i << 1) + 1] = value_u16 + 1; } - const size_t newCustomVRAMBlockSize = _gpuCaptureLineIndex[GPU_VRAM_BLOCK_LINES] * w; - const size_t newCustomVRAMBlankSize = newGpuLargestDstLineCount * GPU_VRAM_BLANK_REGION_LINES * w; - u16 *newCustomVRAM = (u16 *)malloc_alignedCacheLine(((newCustomVRAMBlockSize * 4) + newCustomVRAMBlankSize) * sizeof(u16)); - memset(newCustomVRAM, 0, ((newCustomVRAMBlockSize * 4) + newCustomVRAMBlankSize) * sizeof(u16)); + _gpuLargestDstLineCount = newGpuLargestDstLineCount; + _gpuVRAMBlockOffset = _gpuCaptureLineIndex[GPU_VRAM_BLOCK_LINES] * w; + _gpuDstToSrcIndex = newGpuDstToSrcIndex; + _gpuDstToSrcSSSE3_u8 = newGpuDstToSrcSSSE3_u8; + _gpuDstToSrcSSSE3_u16 = newGpuDstToSrcSSSE3_u16; - const size_t nativeFramebufferSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * sizeof(u16); + this->_displayInfo.isCustomSizeRequested = ( (w != GPU_FRAMEBUFFER_NATIVE_WIDTH) || (h != GPU_FRAMEBUFFER_NATIVE_HEIGHT) ); + this->_displayInfo.customWidth = w; + this->_displayInfo.customHeight = h; + + if (!this->_displayInfo.isCustomSizeRequested) + { + this->_engineMain->nativeLineCaptureCount[0] = GPU_VRAM_BLOCK_LINES; + this->_engineMain->nativeLineCaptureCount[1] = GPU_VRAM_BLOCK_LINES; + this->_engineMain->nativeLineCaptureCount[2] = GPU_VRAM_BLOCK_LINES; + this->_engineMain->nativeLineCaptureCount[3] = GPU_VRAM_BLOCK_LINES; + + for (size_t l = 0; l < GPU_VRAM_BLOCK_LINES; l++) + { + this->_engineMain->isLineCaptureNative[0][l] = true; + this->_engineMain->isLineCaptureNative[1][l] = true; + this->_engineMain->isLineCaptureNative[2][l] = true; + this->_engineMain->isLineCaptureNative[3][l] = true; + } + } + + if (this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main]) + { + this->_displayInfo.renderedWidth[NDSDisplayID_Main] = this->_displayInfo.customWidth; + this->_displayInfo.renderedHeight[NDSDisplayID_Main] = this->_displayInfo.customHeight; + } + else + { + this->_displayInfo.renderedWidth[NDSDisplayID_Main] = GPU_FRAMEBUFFER_NATIVE_WIDTH; + this->_displayInfo.renderedHeight[NDSDisplayID_Main] = GPU_FRAMEBUFFER_NATIVE_HEIGHT; + } + + if (this->_displayInfo.didPerformCustomRender[NDSDisplayID_Touch]) + { + this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = this->_displayInfo.customWidth; + this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = this->_displayInfo.customHeight; + } + else + { + this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = GPU_FRAMEBUFFER_NATIVE_WIDTH; + this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = GPU_FRAMEBUFFER_NATIVE_HEIGHT; + } + + this->_AllocateFramebuffers(this->_displayInfo.colorFormat, w, h, clientNativeBuffer, clientCustomBuffer); + + free_aligned(oldGpuDstToSrcIndexPtr); + free_aligned(oldGpuDstToSrcSSSE3_u8); + free_aligned(oldGpuDstToSrcSSSE3_u16); +} + +void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h) +{ + this->SetCustomFramebufferSize(w, h, NULL, NULL); +} + +void GPUSubsystem::SetColorFormat(const NDSColorFormat outputFormat, void *clientNativeBuffer, void *clientCustomBuffer) +{ + // TBD: Multiple color formats aren't supported in the renderer yet. Force the color format to NDSColorFormat_BGR555_Rev until then. + //this->_displayInfo.colorFormat = outputFormat; + this->_displayInfo.colorFormat = NDSColorFormat_BGR555_Rev; + + this->_displayInfo.pixelBytes = (outputFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(u32); + + this->_AllocateFramebuffers(this->_displayInfo.colorFormat, this->_displayInfo.customWidth, this->_displayInfo.customHeight, clientNativeBuffer, clientCustomBuffer); +} + +void GPUSubsystem::SetColorFormat(const NDSColorFormat outputFormat) +{ + this->SetColorFormat(outputFormat, NULL, NULL); +} + +void GPUSubsystem::_AllocateFramebuffers(NDSColorFormat outputFormat, size_t w, size_t h, void *clientNativeBuffer, void *clientCustomBuffer) +{ + void *oldCustomFramebuffer = this->_customFramebuffer; + void *oldCustomVRAM = this->_customVRAM; + + const size_t pixelBytes = (outputFormat == NDSColorFormat_BGR555_Rev) ? sizeof(u16) : sizeof(FragmentColor); + const size_t newCustomVRAMBlockSize = _gpuCaptureLineIndex[GPU_VRAM_BLOCK_LINES] * w; + const size_t newCustomVRAMBlankSize = _gpuLargestDstLineCount * GPU_VRAM_BLANK_REGION_LINES * w; + const size_t nativeFramebufferSize = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * pixelBytes; + + u16 *newCustomVRAM = (u16 *)malloc_alignedCacheLine(((newCustomVRAMBlockSize * 4) + newCustomVRAMBlankSize) * pixelBytes); + memset(newCustomVRAM, 0, ((newCustomVRAMBlockSize * 4) + newCustomVRAMBlankSize) * pixelBytes); if (clientNativeBuffer != NULL) { @@ -6058,44 +6140,15 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, u16 *clientNativ } else { - u16 *newCustomFramebuffer = (u16 *)malloc_alignedCacheLine(w * h * 2 * sizeof(u16)); + u16 *newCustomFramebuffer = (u16 *)malloc_alignedCacheLine(w * h * 2 * pixelBytes); memset_u16(newCustomFramebuffer, 0x8000, w * h * 2); this->_customFramebuffer = newCustomFramebuffer; this->_displayInfo.masterCustomBuffer = newCustomFramebuffer; } - _gpuLargestDstLineCount = newGpuLargestDstLineCount; - _gpuVRAMBlockOffset = _gpuCaptureLineIndex[GPU_VRAM_BLOCK_LINES] * w; - _gpuDstToSrcIndex = newGpuDstToSrcIndex; - _gpuDstToSrcSSSE3_u8 = newGpuDstToSrcSSSE3_u8; - _gpuDstToSrcSSSE3_u16 = newGpuDstToSrcSSSE3_u16; this->_customVRAM = newCustomVRAM; this->_customVRAMBlank = newCustomVRAM + (newCustomVRAMBlockSize * 4); - this->_displayInfo.isCustomSizeRequested = ( (w != GPU_FRAMEBUFFER_NATIVE_WIDTH) || (h != GPU_FRAMEBUFFER_NATIVE_HEIGHT) ); - this->_displayInfo.customWidth = w; - this->_displayInfo.customHeight = h; - this->_displayInfo.nativeBuffer[NDSDisplayID_Main] = (this->_displayMain->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterNativeBuffer : this->_displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); - this->_displayInfo.nativeBuffer[NDSDisplayID_Touch] = (this->_displayTouch->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterNativeBuffer : this->_displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); - this->_displayInfo.customBuffer[NDSDisplayID_Main] = (this->_displayMain->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterCustomBuffer : this->_displayInfo.masterCustomBuffer + (w * h); - this->_displayInfo.customBuffer[NDSDisplayID_Touch] = (this->_displayTouch->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterCustomBuffer : this->_displayInfo.masterCustomBuffer + (w * h); - - if (!this->_displayInfo.isCustomSizeRequested) - { - this->_engineMain->nativeLineCaptureCount[0] = GPU_VRAM_BLOCK_LINES; - this->_engineMain->nativeLineCaptureCount[1] = GPU_VRAM_BLOCK_LINES; - this->_engineMain->nativeLineCaptureCount[2] = GPU_VRAM_BLOCK_LINES; - this->_engineMain->nativeLineCaptureCount[3] = GPU_VRAM_BLOCK_LINES; - - for (size_t l = 0; l < GPU_VRAM_BLOCK_LINES; l++) - { - this->_engineMain->isLineCaptureNative[0][l] = true; - this->_engineMain->isLineCaptureNative[1][l] = true; - this->_engineMain->isLineCaptureNative[2][l] = true; - this->_engineMain->isLineCaptureNative[3][l] = true; - } - } - this->_engineMain->SetCustomFramebufferSize(w, h); this->_engineSub->SetCustomFramebufferSize(w, h); BaseRenderer->SetFramebufferSize(w, h); // Since BaseRenderer is persistent, we need to update this manually. @@ -6105,44 +6158,18 @@ void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h, u16 *clientNativ CurrentRenderer->SetFramebufferSize(w, h); } - if (this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main]) - { - this->_displayInfo.renderedBuffer[NDSDisplayID_Main] = this->_displayInfo.customBuffer[NDSDisplayID_Main]; - this->_displayInfo.renderedWidth[NDSDisplayID_Main] = this->_displayInfo.customWidth; - this->_displayInfo.renderedHeight[NDSDisplayID_Main] = this->_displayInfo.customHeight; - } - else - { - this->_displayInfo.renderedBuffer[NDSDisplayID_Main] = this->_displayInfo.nativeBuffer[NDSDisplayID_Main]; - this->_displayInfo.renderedWidth[NDSDisplayID_Main] = GPU_FRAMEBUFFER_NATIVE_WIDTH; - this->_displayInfo.renderedHeight[NDSDisplayID_Main] = GPU_FRAMEBUFFER_NATIVE_HEIGHT; - } + this->_displayInfo.nativeBuffer[NDSDisplayID_Main] = (this->_displayMain->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterNativeBuffer : (u8 *)this->_displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * this->_displayInfo.pixelBytes); + this->_displayInfo.nativeBuffer[NDSDisplayID_Touch] = (this->_displayTouch->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterNativeBuffer : (u8 *)this->_displayInfo.masterNativeBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * this->_displayInfo.pixelBytes); + this->_displayInfo.customBuffer[NDSDisplayID_Main] = (this->_displayMain->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterCustomBuffer : (u8 *)this->_displayInfo.masterCustomBuffer + (w * h * this->_displayInfo.pixelBytes); + this->_displayInfo.customBuffer[NDSDisplayID_Touch] = (this->_displayTouch->GetEngine()->GetDisplayByID() == NDSDisplayID_Main) ? this->_displayInfo.masterCustomBuffer : (u8 *)this->_displayInfo.masterCustomBuffer + (w * h * this->_displayInfo.pixelBytes); - if (this->_displayInfo.didPerformCustomRender[NDSDisplayID_Touch]) - { - this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = this->_displayInfo.customBuffer[NDSDisplayID_Touch]; - this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = this->_displayInfo.customWidth; - this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = this->_displayInfo.customHeight; - } - else - { - this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = this->_displayInfo.nativeBuffer[NDSDisplayID_Touch]; - this->_displayInfo.renderedWidth[NDSDisplayID_Touch] = GPU_FRAMEBUFFER_NATIVE_WIDTH; - this->_displayInfo.renderedHeight[NDSDisplayID_Touch] = GPU_FRAMEBUFFER_NATIVE_HEIGHT; - } + this->_displayInfo.renderedBuffer[NDSDisplayID_Main] = (this->_displayInfo.didPerformCustomRender[NDSDisplayID_Main]) ? this->_displayInfo.customBuffer[NDSDisplayID_Main] : this->_displayInfo.nativeBuffer[NDSDisplayID_Main]; + this->_displayInfo.renderedBuffer[NDSDisplayID_Touch] = (this->_displayInfo.didPerformCustomRender[NDSDisplayID_Touch]) ? this->_displayInfo.customBuffer[NDSDisplayID_Touch] : this->_displayInfo.nativeBuffer[NDSDisplayID_Touch]; free_aligned(oldCustomFramebuffer); - free_aligned(oldGpuDstToSrcIndexPtr); - free_aligned(oldGpuDstToSrcSSSE3_u8); - free_aligned(oldGpuDstToSrcSSSE3_u16); free_aligned(oldCustomVRAM); } -void GPUSubsystem::SetCustomFramebufferSize(size_t w, size_t h) -{ - this->SetCustomFramebufferSize(w, h, NULL, NULL); -} - u16* GPUSubsystem::GetCustomVRAMBuffer() { return this->_customVRAM; @@ -6294,8 +6321,48 @@ void GPUSubsystem::RenderLine(const u16 l, bool isFrameSkipRequested) void GPUSubsystem::ClearWithColor(const u16 colorBGRA5551) { - memset_u16(this->_displayInfo.masterNativeBuffer, colorBGRA5551, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2); - memset_u16(this->_displayInfo.masterCustomBuffer, colorBGRA5551, this->_displayInfo.customWidth * this->_displayInfo.customHeight * 2); + u16 color16 = colorBGRA5551; + FragmentColor color32; + + switch (this->_displayInfo.colorFormat) + { + case NDSColorFormat_BGR555_Rev: + color16 = colorBGRA5551 | 0x8000; + break; + + case NDSColorFormat_BGR666_Rev: + color32.r = material_5bit_to_6bit[(colorBGRA5551 & 0x001F)]; + color32.g = material_5bit_to_6bit[(colorBGRA5551 & 0x03E0) >> 5]; + color32.b = material_5bit_to_6bit[(colorBGRA5551 & 0x7C00) >> 10]; + color32.a = 0xFF; + break; + + case NDSColorFormat_BGR888_Rev: + color32.r = material_5bit_to_8bit[(colorBGRA5551 & 0x001F)]; + color32.g = material_5bit_to_8bit[(colorBGRA5551 & 0x03E0) >> 5]; + color32.b = material_5bit_to_8bit[(colorBGRA5551 & 0x7C00) >> 10]; + color32.a = 0xFF; + break; + + default: + break; + } + + switch (this->_displayInfo.pixelBytes) + { + case 2: + memset_u16(this->_displayInfo.masterNativeBuffer, color16, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2); + memset_u16(this->_displayInfo.masterCustomBuffer, color16, this->_displayInfo.customWidth * this->_displayInfo.customHeight * 2); + break; + + case 4: + memset_u32(this->_displayInfo.masterNativeBuffer, color32.color, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2); + memset_u32(this->_displayInfo.masterCustomBuffer, color32.color, this->_displayInfo.customWidth * this->_displayInfo.customHeight * 2); + break; + + default: + break; + } } NDSDisplay::NDSDisplay() diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index 306f95af8..0fd70a036 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -1025,6 +1025,61 @@ enum NDSDisplayID NDSDisplayID_Touch = 1 }; +enum NDSColorFormat +{ + // The color format information is packed in a 32-bit value. + // The bits are as follows: + // FFFOOOOO AAAAAABB BBBBGGGG GGRRRRRR + // + // F = Flags (see below) + // O = Color order (see below) + // A = Bit count for alpha [0-63] + // B = Bit count for blue [0-63] + // G = Bit count for green [0-63] + // R = Bit count for red [0-63] + // + // Flags: + // Bit 29: Reverse order flag. + // Set = Bits are in reverse order, usually for little-endian usage. + // Cleared = Bits are in normal order, usually for big-endian usage. + // + // Color order bits, 24-28: + // 0x00 = RGBA, common format + // 0x01 = RGAB + // 0x02 = RBGA + // 0x03 = RBAG + // 0x04 = RAGB + // 0x05 = RABG + // 0x06 = GRBA + // 0x07 = GRAB + // 0x08 = GBRA + // 0x09 = GBAR + // 0x0A = GARB + // 0x0B = GABR + // 0x0C = BRGA + // 0x0D = BRAG + // 0x0E = BGRA, common format + // 0x0F = BGAR + // 0x10 = BARG + // 0x11 = BAGR + // 0x12 = ARGB + // 0x13 = ARBG + // 0x14 = AGRB + // 0x15 = AGBR + // 0x16 = ABRG + // 0x17 = ABGR + + // Color formats used for internal processing. + //NDSColorFormat_ABGR1555_Rev = 0x20045145, + //NDSColorFormat_ABGR5666_Rev = 0x20186186, + //NDSColorFormat_ABGR8888_Rev = 0x20208208, + + // Color formats used by the output framebuffers. + NDSColorFormat_BGR555_Rev = 0x20005145, + NDSColorFormat_BGR666_Rev = 0x20006186, + NDSColorFormat_BGR888_Rev = 0x20008208 +}; + struct DISPCAPCNT_parsed { u8 EVA; @@ -1035,33 +1090,37 @@ struct DISPCAPCNT_parsed typedef struct { - // User-requested settings. These fields will always remain constant, and can only be changed if - // the user calls GPUSubsystem::SetFramebufferSize(). + // User-requested settings. These fields will always remain constant until changed. + // Changed by calling GPUSubsystem::SetColorFormat(). + // TBD: The color format will always be 2-byte NDSColorFormat_BGR555_Rev until internal rendering in multiple formats is fully supported. + NDSColorFormat colorFormat; // The output color format. + size_t pixelBytes; // The number of bytes per pixel. + + // Changed by calling GPUSubsystem::SetFramebufferSize(). bool isCustomSizeRequested; // Reports that the call to GPUSubsystem::SetFramebufferSize() resulted in a custom rendering size. // true - The user requested a custom size. // false - The user requested the native size. size_t customWidth; // The requested custom width, measured in pixels. size_t customHeight; // The requested custom height, measured in pixels. - u16 *masterNativeBuffer; // Pointer to the head of the master native buffer. - u16 *masterCustomBuffer; // Pointer to the head of the master custom buffer. + void *masterNativeBuffer; // Pointer to the head of the master native buffer. + void *masterCustomBuffer; // Pointer to the head of the master custom buffer. // If GPUSubsystem::GetWillAutoResolveToCustomBuffer() would return true, or if // GPUEngineBase::ResolveToCustomFramebuffer() is called, then this buffer is used as the target // buffer for resolving any native-sized renders. // Frame information. These fields will change per frame, depending on how each display was rendered. - - u16 *nativeBuffer[2]; // Pointer to the display's native size framebuffer. - u16 *customBuffer[2]; // Pointer to the display's custom size framebuffer. + void *nativeBuffer[2]; // Pointer to the display's native size framebuffer. + void *customBuffer[2]; // Pointer to the display's custom size framebuffer. bool didPerformCustomRender[2]; // Reports that the display actually rendered at a custom size for this frame. // true - The display performed a custom-sized render. // false - The display performed a native-sized render. size_t renderedWidth[2]; // The display rendered at this width, measured in pixels. size_t renderedHeight[2]; // The display rendered at this height, measured in pixels. - u16 *renderedBuffer[2]; // The display rendered to this buffer. + void *renderedBuffer[2]; // The display rendered to this buffer. } NDSDisplayInfo; #define VRAM_NO_3D_USAGE 0xFF @@ -1508,6 +1567,8 @@ private: NDSDisplayInfo _displayInfo; + void _AllocateFramebuffers(NDSColorFormat outputFormat, size_t w, size_t h, void *clientNativeBuffer, void *clientCustomBuffer); + public: static GPUSubsystem* Allocate(); void FinalizeAndDeallocate(); @@ -1530,8 +1591,10 @@ public: size_t GetCustomFramebufferWidth() const; size_t GetCustomFramebufferHeight() const; - void SetCustomFramebufferSize(size_t w, size_t h, u16 *clientNativeBuffer, u16 *clientCustomBuffer); + void SetCustomFramebufferSize(size_t w, size_t h, void *clientNativeBuffer, void *clientCustomBuffer); void SetCustomFramebufferSize(size_t w, size_t h); + void SetColorFormat(const NDSColorFormat outputFormat, void *clientNativeBuffer, void *clientCustomBuffer); + void SetColorFormat(const NDSColorFormat outputFormat); void UpdateRenderProperties(); diff --git a/desmume/src/cli/main.cpp b/desmume/src/cli/main.cpp index 81f5c4162..b0fa54dbc 100644 --- a/desmume/src/cli/main.cpp +++ b/desmume/src/cli/main.cpp @@ -371,7 +371,7 @@ resizeWindow( u16 width, u16 height, GLuint *screen_texture) { static void opengl_Draw( GLuint *texture, int software_convert) { GLenum errCode; - u16 *gpuFramebuffer = GPU->GetDisplayInfo().masterNativeBuffer; + u16 *gpuFramebuffer = (u16 *)GPU->GetDisplayInfo().masterNativeBuffer; /* Clear The Screen And The Depth Buffer */ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); @@ -446,7 +446,7 @@ static void Draw( void) { SDL_Surface *rawImage; - rawImage = SDL_CreateRGBSurfaceFrom((void*)GPU->GetDisplayInfo().masterNativeBuffer, 256, 384, 16, 512, 0x001F, 0x03E0, 0x7C00, 0); + rawImage = SDL_CreateRGBSurfaceFrom(GPU->GetDisplayInfo().masterNativeBuffer, 256, 384, 16, 512, 0x001F, 0x03E0, 0x7C00, 0); if(rawImage == NULL) return; SDL_BlitSurface(rawImage, 0, surface, 0); diff --git a/desmume/src/cocoa/OGLDisplayOutput.cpp b/desmume/src/cocoa/OGLDisplayOutput.cpp index 6c2fde936..23de7955c 100644 --- a/desmume/src/cocoa/OGLDisplayOutput.cpp +++ b/desmume/src/cocoa/OGLDisplayOutput.cpp @@ -6789,6 +6789,8 @@ OGLDisplayLayer::OGLDisplayLayer(OGLVideoOutput *oglVO) _texLoadedHeight[0] = (GLfloat)GPU_DISPLAY_HEIGHT; _texLoadedHeight[1] = (GLfloat)GPU_DISPLAY_HEIGHT; + _videoColorFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV; + _videoSrcBufferHead = NULL; _videoSrcNativeBuffer[0] = NULL; _videoSrcNativeBuffer[1] = NULL; _videoSrcCustomBuffer[0] = NULL; @@ -7061,7 +7063,8 @@ void OGLDisplayLayer::DetermineTextureStorageHints(GLint &videoSrcTexStorageHint glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, this->_useClientStorage); } -void OGLDisplayLayer::SetVideoBuffers(const void *videoBufferHead, +void OGLDisplayLayer::SetVideoBuffers(const uint32_t colorFormat, + const void *videoBufferHead, const void *nativeBuffer0, const void *nativeBuffer1, const void *customBuffer0, const size_t customWidth0, const size_t customHeight0, @@ -7070,12 +7073,17 @@ void OGLDisplayLayer::SetVideoBuffers(const void *videoBufferHead, GLint videoSrcTexStorageHint = GL_STORAGE_PRIVATE_APPLE; GLint cpuFilterTexStorageHint = GL_STORAGE_PRIVATE_APPLE; - this->_videoSrcBufferHead = (uint16_t *)videoBufferHead; - this->_videoSrcBufferSize = (GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT * 2 * sizeof(uint16_t)) + (customWidth0 * customHeight0 * sizeof(uint16_t)) + (customWidth1 * customHeight1 * sizeof(uint16_t)); - this->_videoSrcNativeBuffer[0] = (uint16_t *)nativeBuffer0; - this->_videoSrcNativeBuffer[1] = (uint16_t *)nativeBuffer1; - this->_videoSrcCustomBuffer[0] = (uint16_t *)customBuffer0; - this->_videoSrcCustomBuffer[1] = (uint16_t *)customBuffer1; + const u8 bitCount = (colorFormat & 0x0000003F); + const GLenum glColorFormat = (bitCount == 5) ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_INT_8_8_8_8_REV; + const size_t pixelBytes = (glColorFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV) ? sizeof(uint16_t) : sizeof(uint32_t); + + this->_videoColorFormat = glColorFormat; + this->_videoSrcBufferHead = videoBufferHead; + this->_videoSrcBufferSize = (GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT * 2 * pixelBytes) + (customWidth0 * customHeight0 * pixelBytes) + (customWidth1 * customHeight1 * pixelBytes); + this->_videoSrcNativeBuffer[0] = nativeBuffer0; + this->_videoSrcNativeBuffer[1] = nativeBuffer1; + this->_videoSrcCustomBuffer[0] = customBuffer0; + this->_videoSrcCustomBuffer[1] = customBuffer1; this->_videoSrcCustomBufferWidth[0] = customWidth0; this->_videoSrcCustomBufferWidth[1] = customWidth1; this->_videoSrcCustomBufferHeight[0] = customHeight0; @@ -7093,19 +7101,19 @@ void OGLDisplayLayer::SetVideoBuffers(const void *videoBufferHead, glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[0]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_videoSrcNativeBuffer[0]); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, 0, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[0]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[1]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_videoSrcNativeBuffer[1]); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, 0, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[1]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[0]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_videoSrcCustomBufferWidth[0], this->_videoSrcCustomBufferHeight[0], 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_videoSrcCustomBuffer[0]); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_videoSrcCustomBufferWidth[0], this->_videoSrcCustomBufferHeight[0], 0, GL_RGBA, this->_videoColorFormat, this->_videoSrcCustomBuffer[0]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[1]); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE, videoSrcTexStorageHint); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_videoSrcCustomBufferWidth[1], this->_videoSrcCustomBufferHeight[1], 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_videoSrcCustomBuffer[1]); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, this->_videoSrcCustomBufferWidth[1], this->_videoSrcCustomBufferHeight[1], 0, GL_RGBA, this->_videoColorFormat, this->_videoSrcCustomBuffer[1]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); @@ -7837,19 +7845,26 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative if (!isUsingCPUPixelScaler || this->_useDeposterize) { glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[0]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_videoSrcNativeBuffer[0]); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[0]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glFlush(); } else { - RGB555ToBGRA8888Buffer(this->_videoSrcNativeBuffer[0], this->_vf[0]->GetSrcBufferPtr(), GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); + if (this->_videoColorFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV) + { + RGB555ToBGRA8888Buffer((const uint16_t *)this->_videoSrcNativeBuffer[0], this->_vf[0]->GetSrcBufferPtr(), GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); + } + else + { + RGB888ToBGRA8888Buffer((const uint32_t *)this->_videoSrcNativeBuffer[0], this->_vf[0]->GetSrcBufferPtr(), GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); + } } } else { glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[0]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->_videoSrcCustomBufferWidth[0], this->_videoSrcCustomBufferHeight[0], GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_videoSrcCustomBuffer[0]); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->_videoSrcCustomBufferWidth[0], this->_videoSrcCustomBufferHeight[0], GL_RGBA, this->_videoColorFormat, this->_videoSrcCustomBuffer[0]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glFlush(); } @@ -7872,19 +7887,26 @@ void OGLDisplayLayer::LoadFrameOGL(bool isMainSizeNative, bool isTouchSizeNative if (!isUsingCPUPixelScaler || this->_useDeposterize) { glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataNativeID[1]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_videoSrcNativeBuffer[1]); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GPU_DISPLAY_WIDTH, GPU_DISPLAY_HEIGHT, GL_RGBA, this->_videoColorFormat, this->_videoSrcNativeBuffer[1]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glFlush(); } else { - RGB555ToBGRA8888Buffer(this->_videoSrcNativeBuffer[1], this->_vf[1]->GetSrcBufferPtr(), GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); + if (this->_videoColorFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV) + { + RGB555ToBGRA8888Buffer((const uint16_t *)this->_videoSrcNativeBuffer[1], this->_vf[1]->GetSrcBufferPtr(), GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); + } + else + { + RGB888ToBGRA8888Buffer((const uint32_t *)this->_videoSrcNativeBuffer[1], this->_vf[1]->GetSrcBufferPtr(), GPU_DISPLAY_WIDTH * GPU_DISPLAY_HEIGHT); + } } } else { glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->_texVideoInputDataCustomID[1]); - glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->_videoSrcCustomBufferWidth[1], this->_videoSrcCustomBufferHeight[1], GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, this->_videoSrcCustomBuffer[1]); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, this->_videoSrcCustomBufferWidth[1], this->_videoSrcCustomBufferHeight[1], GL_RGBA, this->_videoColorFormat, this->_videoSrcCustomBuffer[1]); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glFlush(); } diff --git a/desmume/src/cocoa/OGLDisplayOutput.h b/desmume/src/cocoa/OGLDisplayOutput.h index e24b1e8d7..4cd259990 100644 --- a/desmume/src/cocoa/OGLDisplayOutput.h +++ b/desmume/src/cocoa/OGLDisplayOutput.h @@ -400,10 +400,11 @@ protected: GLfloat _texLoadedWidth[2]; GLfloat _texLoadedHeight[2]; - uint16_t *_videoSrcBufferHead; + GLenum _videoColorFormat; + const void *_videoSrcBufferHead; + const void *_videoSrcNativeBuffer[2]; + const void *_videoSrcCustomBuffer[2]; size_t _videoSrcBufferSize; - uint16_t *_videoSrcNativeBuffer[2]; - uint16_t *_videoSrcCustomBuffer[2]; GLsizei _videoSrcCustomBufferWidth[2]; GLsizei _videoSrcCustomBufferHeight[2]; @@ -456,7 +457,8 @@ public: OGLDisplayLayer(OGLVideoOutput *oglVO); virtual ~OGLDisplayLayer(); - void SetVideoBuffers(const void *videoBufferHead, + void SetVideoBuffers(const uint32_t colorFormat, + const void *videoBufferHead, const void *nativeBuffer0, const void *nativeBuffer1, const void *customBuffer0, const size_t customWidth0, const size_t customHeight0, diff --git a/desmume/src/cocoa/cocoa_output.h b/desmume/src/cocoa/cocoa_output.h index 1aeb49c59..7ef2b4347 100644 --- a/desmume/src/cocoa/cocoa_output.h +++ b/desmume/src/cocoa/cocoa_output.h @@ -118,15 +118,16 @@ typedef struct @required - (void) doInitVideoOutput:(NSDictionary *)properties; -- (void) doSetVideoBuffers:(const uint16_t *)videoBufferHead - nativeBuffer0:(const uint16_t *)nativeBuffer0 - nativeBuffer1:(const uint16_t *)nativeBuffer1 - customBuffer0:(const uint16_t *)customBuffer0 - customWidth0:(const size_t)customWidth0 - customHeight0:(const size_t)customHeight0 - customBuffer1:(const uint16_t *)customBuffer1 - customWidth1:(const size_t)customWidth1 - customHeight1:(const size_t)customHeight1; +- (void) doSetVideoBuffersUsingFormat:(const uint32_t)colorFormat + bufferHead:(const void *)videoBufferHead + nativeBuffer0:(const void *)nativeBuffer0 + nativeBuffer1:(const void *)nativeBuffer1 + customBuffer0:(const void *)customBuffer0 + customWidth0:(const size_t)customWidth0 + customHeight0:(const size_t)customHeight0 + customBuffer1:(const void *)customBuffer1 + customWidth1:(const size_t)customWidth1 + customHeight1:(const size_t)customHeight1; - (void) doLoadVideoFrameWithMainSizeNative:(bool)isMainSizeNative touchSizeNative:(bool)isTouchSizeNative; @@ -183,9 +184,9 @@ typedef struct @interface CocoaDSDisplayVideo : CocoaDSDisplay { - uint16_t *_videoBuffer; - uint16_t *_nativeBuffer[2]; - uint16_t *_customBuffer[2]; + void *_videoBuffer; + void *_nativeBuffer[2]; + void *_customBuffer[2]; } - (void) handleReceiveGPUFrame; diff --git a/desmume/src/cocoa/cocoa_output.mm b/desmume/src/cocoa/cocoa_output.mm index 9f39c8daf..1c742f606 100644 --- a/desmume/src/cocoa/cocoa_output.mm +++ b/desmume/src/cocoa/cocoa_output.mm @@ -725,7 +725,6 @@ const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); const NSInteger dispMode = [self displayMode]; - uint16_t *displayBuffer = dispInfo.masterCustomBuffer; NSUInteger w = (NSUInteger)dispInfo.customWidth; NSUInteger h = (dispMode == DS_DISPLAY_TYPE_DUAL) ? (NSUInteger)(dispInfo.customHeight * 2) : (NSUInteger)dispInfo.customHeight; @@ -745,12 +744,23 @@ return imageRep; } + void *displayBuffer = dispInfo.masterCustomBuffer; uint32_t *bitmapData = (uint32_t *)[imageRep bitmapData]; pthread_rwlock_rdlock(self.rwlockProducer); + GPU->GetEngineMain()->ResolveToCustomFramebuffer(); GPU->GetEngineSub()->ResolveToCustomFramebuffer(); - RGB555ToRGBA8888Buffer(displayBuffer, bitmapData, (w * h)); + + if (dispInfo.pixelBytes == 2) + { + RGB555ToRGBA8888Buffer((u16 *)displayBuffer, bitmapData, (w * h)); + } + else if (dispInfo.pixelBytes == 4) + { + RGBA8888ForceOpaqueBuffer((u32 *)displayBuffer, bitmapData, (w * h)); + } + pthread_rwlock_unlock(self.rwlockProducer); #ifdef __BIG_ENDIAN__ @@ -904,23 +914,23 @@ if (isMainSizeNative && isTouchSizeNative) { - memcpy(_nativeBuffer[NDSDisplayID_Main], dispInfo.masterNativeBuffer, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * sizeof(uint16_t)); + memcpy(_nativeBuffer[NDSDisplayID_Main], dispInfo.masterNativeBuffer, GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * dispInfo.pixelBytes); } else { if (!isMainSizeNative && !isTouchSizeNative) { - memcpy(_customBuffer[NDSDisplayID_Main], dispInfo.masterCustomBuffer, dispInfo.customWidth * dispInfo.customHeight * 2 * sizeof(uint16_t)); + memcpy(_customBuffer[NDSDisplayID_Main], dispInfo.masterCustomBuffer, dispInfo.customWidth * dispInfo.customHeight * 2 * dispInfo.pixelBytes); } else if (isTouchSizeNative) { - memcpy(_customBuffer[NDSDisplayID_Main], dispInfo.customBuffer[NDSDisplayID_Main], dispInfo.customWidth * dispInfo.customHeight * sizeof(uint16_t)); - memcpy(_nativeBuffer[NDSDisplayID_Touch], dispInfo.nativeBuffer[NDSDisplayID_Touch], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(uint16_t)); + memcpy(_customBuffer[NDSDisplayID_Main], dispInfo.customBuffer[NDSDisplayID_Main], dispInfo.customWidth * dispInfo.customHeight * dispInfo.pixelBytes); + memcpy(_nativeBuffer[NDSDisplayID_Touch], dispInfo.nativeBuffer[NDSDisplayID_Touch], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * dispInfo.pixelBytes); } else { - memcpy(_nativeBuffer[NDSDisplayID_Main], dispInfo.nativeBuffer[NDSDisplayID_Main], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * sizeof(uint16_t)); - memcpy(_customBuffer[NDSDisplayID_Touch], dispInfo.customBuffer[NDSDisplayID_Touch], dispInfo.customWidth * dispInfo.customHeight * sizeof(uint16_t)); + memcpy(_nativeBuffer[NDSDisplayID_Main], dispInfo.nativeBuffer[NDSDisplayID_Main], GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * dispInfo.pixelBytes); + memcpy(_customBuffer[NDSDisplayID_Touch], dispInfo.customBuffer[NDSDisplayID_Touch], dispInfo.customWidth * dispInfo.customHeight * dispInfo.pixelBytes); } } @@ -1006,25 +1016,43 @@ - (void) resetVideoBuffers { + size_t pixelBytes = sizeof(uint16_t); const NDSDisplayInfo &dispInfo = GPU->GetDisplayInfo(); - uint16_t *oldVideoBuffer = _videoBuffer; - uint16_t *newVideoBuffer = (uint16_t *)malloc_alignedCacheLine( ((GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT) + (dispInfo.customWidth * dispInfo.customHeight)) * 2 * sizeof(uint16_t) ); - [(id)delegate doSetVideoBuffers:newVideoBuffer - nativeBuffer0:newVideoBuffer - nativeBuffer1:newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT) - customBuffer0:newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2) - customWidth0:dispInfo.customWidth - customHeight0:dispInfo.customHeight - customBuffer1:newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2) + (dispInfo.customWidth * dispInfo.customHeight) - customWidth1:dispInfo.customWidth - customHeight1:dispInfo.customHeight]; + switch (dispInfo.colorFormat) + { + case NDSColorFormat_BGR555_Rev: + pixelBytes = sizeof(uint16_t); + break; + + case NDSColorFormat_BGR666_Rev: + case NDSColorFormat_BGR888_Rev: + pixelBytes = sizeof(uint32_t); + break; + + default: + break; + } + + void *oldVideoBuffer = _videoBuffer; + uint8_t *newVideoBuffer = (uint8_t *)malloc_alignedCacheLine( ((GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT) + (dispInfo.customWidth * dispInfo.customHeight)) * 2 * pixelBytes ); + + [(id)delegate doSetVideoBuffersUsingFormat:dispInfo.colorFormat + bufferHead:newVideoBuffer + nativeBuffer0:newVideoBuffer + nativeBuffer1:newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * pixelBytes) + customBuffer0:newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * pixelBytes) + customWidth0:dispInfo.customWidth + customHeight0:dispInfo.customHeight + customBuffer1:newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * pixelBytes) + (dispInfo.customWidth * dispInfo.customHeight * pixelBytes) + customWidth1:dispInfo.customWidth + customHeight1:dispInfo.customHeight]; _videoBuffer = newVideoBuffer; _nativeBuffer[NDSDisplayID_Main] = newVideoBuffer; - _nativeBuffer[NDSDisplayID_Touch] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT); - _customBuffer[NDSDisplayID_Main] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2); - _customBuffer[NDSDisplayID_Touch] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2) + (dispInfo.customWidth * dispInfo.customHeight); + _nativeBuffer[NDSDisplayID_Touch] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * pixelBytes); + _customBuffer[NDSDisplayID_Main] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * pixelBytes); + _customBuffer[NDSDisplayID_Touch] = newVideoBuffer + (GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2 * pixelBytes) + (dispInfo.customWidth * dispInfo.customHeight * pixelBytes); free_aligned(oldVideoBuffer); } diff --git a/desmume/src/cocoa/userinterface/DisplayWindowController.mm b/desmume/src/cocoa/userinterface/DisplayWindowController.mm index 872f1e95d..83ea5a24f 100644 --- a/desmume/src/cocoa/userinterface/DisplayWindowController.mm +++ b/desmume/src/cocoa/userinterface/DisplayWindowController.mm @@ -2288,21 +2288,23 @@ static std::unordered_map _screenMap; // CGLUnlockContext(cglDisplayContext); } -- (void)doSetVideoBuffers:(const uint16_t *)videoBufferHead - nativeBuffer0:(const uint16_t *)nativeBuffer0 - nativeBuffer1:(const uint16_t *)nativeBuffer1 - customBuffer0:(const uint16_t *)customBuffer0 - customWidth0:(const size_t)customWidth0 - customHeight0:(const size_t)customHeight0 - customBuffer1:(const uint16_t *)customBuffer1 - customWidth1:(const size_t)customWidth1 - customHeight1:(const size_t)customHeight1 +- (void) doSetVideoBuffersUsingFormat:(const uint32_t)colorFormat + bufferHead:(const void *)videoBufferHead + nativeBuffer0:(const void *)nativeBuffer0 + nativeBuffer1:(const void *)nativeBuffer1 + customBuffer0:(const void *)customBuffer0 + customWidth0:(const size_t)customWidth0 + customHeight0:(const size_t)customHeight0 + customBuffer1:(const void *)customBuffer1 + customWidth1:(const size_t)customWidth1 + customHeight1:(const size_t)customHeight1 { OGLDisplayLayer *displayLayer = oglv->GetDisplayLayer(); CGLLockContext(cglDisplayContext); CGLSetCurrentContext(cglDisplayContext); - displayLayer->SetVideoBuffers(videoBufferHead, + displayLayer->SetVideoBuffers(colorFormat, + videoBufferHead, nativeBuffer0, nativeBuffer1, customBuffer0, customWidth0, customHeight0, diff --git a/desmume/src/cocoa/utilities.c b/desmume/src/cocoa/utilities.c index 2db026a16..d7a539dd2 100644 --- a/desmume/src/cocoa/utilities.c +++ b/desmume/src/cocoa/utilities.c @@ -170,6 +170,28 @@ inline uint32_t RGB555ToBGRA8888(const uint16_t color16) 0xFF000000; } +/******************************************************************************************** + RGB888ToBGRA8888() - INLINE + + Converts a color from 24-bit RGB888 format into 32-bit BGRA8888 format. + + Takes: + color32 - The pixel in 24-bit RGB888 format. + + Returns: + A 32-bit unsigned integer containing the BGRA8888 formatted color. + + Details: + The input and output pixels are expected to have little-endian byte order. + ********************************************************************************************/ +inline uint32_t RGB888ToBGRA8888(const uint32_t color32) +{ + return ((color32 & 0x000000FF) << 16) | + ((color32 & 0x0000FF00) ) | + ((color32 & 0x00FF0000) >> 16) | + 0xFF000000; +} + /******************************************************************************************** RGBA8888ForceOpaque() - INLINE @@ -249,6 +271,36 @@ void RGB555ToBGRA8888Buffer(const uint16_t *__restrict__ srcBuffer, uint32_t *__ } } +/******************************************************************************************** + RGB888ToBGRA8888Buffer() + + Copies a 24-bit RGB888 pixel buffer into a 32-bit BGRA8888 pixel buffer. + + Takes: + srcBuffer - Pointer to the source 24-bit RGB888 pixel buffer. + + destBuffer - Pointer to the destination 32-bit BGRA8888 pixel buffer. + + pixelCount - The number of pixels to copy. + + Returns: + Nothing. + + Details: + The source and destination pixels are expected to have little-endian byte order. + Also, it is the caller's responsibility to ensure that the source and destination + buffers are large enough to accomodate the requested number of pixels. + ********************************************************************************************/ +void RGB888ToBGRA8888Buffer(const uint32_t *__restrict__ srcBuffer, uint32_t *__restrict__ destBuffer, size_t pixelCount) +{ + const uint32_t *__restrict__ destBufferEnd = destBuffer + pixelCount; + + while (destBuffer < destBufferEnd) + { + *destBuffer++ = RGB888ToBGRA8888(*srcBuffer++); + } +} + /******************************************************************************************** RGBA8888ForceOpaqueBuffer() diff --git a/desmume/src/cocoa/utilities.h b/desmume/src/cocoa/utilities.h index f735b6649..758add3c2 100644 --- a/desmume/src/cocoa/utilities.h +++ b/desmume/src/cocoa/utilities.h @@ -31,9 +31,11 @@ bool IsOSXVersionSupported(const unsigned int major, const unsigned int minor, c uint32_t RGB555ToRGBA8888(const uint16_t color16); uint32_t RGB555ToBGRA8888(const uint16_t color16); +uint32_t RGB888ToBGRA8888(const uint32_t color32); uint32_t RGBA8888ForceOpaque(const uint32_t color32); void RGB555ToRGBA8888Buffer(const uint16_t *__restrict__ srcBuffer, uint32_t *__restrict__ destBuffer, size_t pixelCount); void RGB555ToBGRA8888Buffer(const uint16_t *__restrict__ srcBuffer, uint32_t *__restrict__ destBuffer, size_t pixelCount); +void RGB888ToBGRA8888Buffer(const uint32_t *__restrict__ srcBuffer, uint32_t *__restrict__ destBuffer, size_t pixelCount); void RGBA8888ForceOpaqueBuffer(const uint32_t *__restrict__ srcBuffer, uint32_t *__restrict__ destBuffer, size_t pixelCount); CGSize GetTransformedBounds(const double normalBoundsWidth, const double normalBoundsHeight, diff --git a/desmume/src/gfx3d.h b/desmume/src/gfx3d.h index a1af4b724..ff4b66404 100644 --- a/desmume/src/gfx3d.h +++ b/desmume/src/gfx3d.h @@ -739,6 +739,7 @@ extern CACHE_ALIGN u16 color_15bit_to_16bit_reverse[32768]; extern CACHE_ALIGN u32 dsDepthExtend_15bit_to_24bit[32768]; extern CACHE_ALIGN u8 mixTable555[32][32][32]; extern CACHE_ALIGN const u32 material_5bit_to_31bit[32]; +extern CACHE_ALIGN const u8 material_5bit_to_6bit[32]; extern CACHE_ALIGN const u8 material_5bit_to_8bit[32]; extern CACHE_ALIGN const u8 material_3bit_to_5bit[8]; extern CACHE_ALIGN const u8 material_3bit_to_6bit[8]; diff --git a/desmume/src/gtk-glade/callbacks.cpp b/desmume/src/gtk-glade/callbacks.cpp index 13a642694..830a807ff 100755 --- a/desmume/src/gtk-glade/callbacks.cpp +++ b/desmume/src/gtk-glade/callbacks.cpp @@ -221,7 +221,7 @@ static void Printscreen() gchar *filename; GError *error = NULL; u8 *rgb; - u16 *gpuFramebuffer = GPU->GetDisplayInfo().masterNativeBuffer; + u16 *gpuFramebuffer = (u16 *)GPU->GetDisplayInfo().masterNativeBuffer; static int seq = 0; rgb = (u8 *) malloc(SCREENS_PIXEL_SIZE*3); diff --git a/desmume/src/gtk-glade/callbacks_IO.cpp b/desmume/src/gtk-glade/callbacks_IO.cpp index f707ba939..5af33f5e0 100755 --- a/desmume/src/gtk-glade/callbacks_IO.cpp +++ b/desmume/src/gtk-glade/callbacks_IO.cpp @@ -117,7 +117,7 @@ static void decode_screen () { int x,y, m, W,H,L,BL; u32 image[RAW_H*2][RAW_W], pix; - u16 * pixel = GPU->GetDisplayInfo().masterNativeBuffer; + u16 * pixel = (u16 *)GPU->GetDisplayInfo().masterNativeBuffer; u32 * rgb32 = &on_screen_image32[0]; /* decode colors */ diff --git a/desmume/src/gtk/main.cpp b/desmume/src/gtk/main.cpp index 750ac15de..81d4646fd 100644 --- a/desmume/src/gtk/main.cpp +++ b/desmume/src/gtk/main.cpp @@ -1547,7 +1547,7 @@ static inline void RGB555ToBGRA8888Buffer(const uint16_t *__restrict__ srcBuffer static inline void gpu_screen_to_rgb(u32* dst) { - RGB555ToRGBA8888Buffer(GPU->GetDisplayInfo().masterNativeBuffer, dst, 256 * 384); + RGB555ToRGBA8888Buffer((const uint16_t *)GPU->GetDisplayInfo().masterNativeBuffer, dst, 256 * 384); } static inline void drawScreen(cairo_t* cr, u32* buf, gint w, gint h) { @@ -1672,7 +1672,7 @@ static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpo } static void RedrawScreen() { - RGB555ToBGRA8888Buffer(GPU->GetDisplayInfo().masterNativeBuffer, video->GetSrcBufferPtr(), 256 * 384); + RGB555ToBGRA8888Buffer((const uint16_t *)GPU->GetDisplayInfo().masterNativeBuffer, video->GetSrcBufferPtr(), 256 * 384); #ifdef HAVE_LIBAGG aggDraw.hud->attach((u8*)video->GetSrcBufferPtr(), 256, 384, 1024); osd->update(); @@ -2437,7 +2437,7 @@ gboolean EmuLoop(gpointer data) desmume_cycle(); /* Emule ! */ _updateDTools(); - avout_x264.updateVideo(GPU->GetDisplayInfo().masterNativeBuffer); + avout_x264.updateVideo((const uint16_t *)GPU->GetDisplayInfo().masterNativeBuffer); RedrawScreen(); if (!config.fpslimiter || keys_latch & KEYMASK_(KEY_BOOST - 1)) { diff --git a/desmume/src/qt/project/frontend/video.cpp b/desmume/src/qt/project/frontend/video.cpp index a14a23cb5..ee9b36ae0 100644 --- a/desmume/src/qt/project/frontend/video.cpp +++ b/desmume/src/qt/project/frontend/video.cpp @@ -106,7 +106,7 @@ bool Video::setFilter(VideoFilterTypeID filterID) { } unsigned int* Video::runFilter() { - RGB555ToRGBA8888Buffer(GPU->GetDisplayInfo().masterNativeBuffer, this->mFilter.GetSrcBufferPtr(), 256 * 384); + RGB555ToRGBA8888Buffer((const uint16_t *)GPU->GetDisplayInfo().masterNativeBuffer, this->mFilter.GetSrcBufferPtr(), 256 * 384); unsigned int* buf = this->mFilter.RunFilter(); this->screenBufferUpdated(buf, this->getDstSize(), this->getDstScale()); return buf; diff --git a/desmume/src/windows/aviout.cpp b/desmume/src/windows/aviout.cpp index 5dff6d379..8757a534d 100644 --- a/desmume/src/windows/aviout.cpp +++ b/desmume/src/windows/aviout.cpp @@ -419,7 +419,7 @@ void DRV_AviVideoUpdate() return; const NDSDisplayInfo& dispInfo = GPU->GetDisplayInfo(); - const u16* buffer = dispInfo.masterCustomBuffer; + const u16* buffer = (const u16 *)dispInfo.masterCustomBuffer; //dont do anything if prescale has changed, it's just going to be garbage if(video.prescaleHD != avi_file->prescaleLevel) diff --git a/desmume/src/windows/hotkey.cpp b/desmume/src/windows/hotkey.cpp index 9b34d2aa1..7f3a80313 100644 --- a/desmume/src/windows/hotkey.cpp +++ b/desmume/src/windows/hotkey.cpp @@ -164,13 +164,13 @@ void HK_QuickScreenShot(int param, bool justPressed) case path.PNG: { strcat(fname, ".png"); - NDS_WritePNG_16bpp(dispInfo.customWidth, dispInfo.customHeight*2, dispInfo.masterCustomBuffer, fname); + NDS_WritePNG_16bpp(dispInfo.customWidth, dispInfo.customHeight*2, (const u16 *)dispInfo.masterCustomBuffer, fname); } break; case path.BMP: { strcat(fname, ".bmp"); - NDS_WriteBMP_16bpp(dispInfo.customWidth, dispInfo.customHeight *2, dispInfo.masterCustomBuffer, fname); + NDS_WriteBMP_16bpp(dispInfo.customWidth, dispInfo.customHeight *2, (const u16 *)dispInfo.masterCustomBuffer, fname); } break; } @@ -224,9 +224,9 @@ void HK_PrintScreen(int param, bool justPressed) filename = outFilename; if(toupper(strright(filename,4)) == ".PNG") - NDS_WritePNG_16bpp(dispInfo.customWidth, dispInfo.customHeight*2, dispInfo.masterCustomBuffer, filename.c_str()); + NDS_WritePNG_16bpp(dispInfo.customWidth, dispInfo.customHeight*2, (const u16 *)dispInfo.masterCustomBuffer, filename.c_str()); else if(toupper(strright(filename,4)) == ".BMP") - NDS_WriteBMP_16bpp(dispInfo.customWidth, dispInfo.customHeight*2, dispInfo.masterCustomBuffer, filename.c_str()); + NDS_WriteBMP_16bpp(dispInfo.customWidth, dispInfo.customHeight*2, (const u16 *)dispInfo.masterCustomBuffer, filename.c_str()); } if(unpause) NDS_UnPause(false);