Merge pull request #8441 from unknownbrackets/gpu-mpeg

Use video format when uploading directly to framebuffers
This commit is contained in:
Henrik Rydgård 2016-01-17 22:01:56 +01:00
commit c19335ff98
17 changed files with 63 additions and 6 deletions

View File

@ -1094,7 +1094,7 @@ static u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr
// playing all pmp_queue frames // playing all pmp_queue frames
ctx->mediaengine->m_pFrameRGB = pmp_queue.front(); ctx->mediaengine->m_pFrameRGB = pmp_queue.front();
int bufferSize = ctx->mediaengine->writeVideoImage(buffer, frameWidth, ctx->videoPixelMode); int bufferSize = ctx->mediaengine->writeVideoImage(buffer, frameWidth, ctx->videoPixelMode);
gpu->InvalidateCache(buffer, bufferSize, GPU_INVALIDATE_SAFE); gpu->NotifyVideoUpload(buffer, bufferSize, frameWidth, ctx->videoPixelMode);
ctx->avc.avcFrameStatus = 1; ctx->avc.avcFrameStatus = 1;
ctx->videoFrameCount++; ctx->videoFrameCount++;
@ -1105,7 +1105,7 @@ static u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr
} }
else if(ctx->mediaengine->stepVideo(ctx->videoPixelMode)) { else if(ctx->mediaengine->stepVideo(ctx->videoPixelMode)) {
int bufferSize = ctx->mediaengine->writeVideoImage(buffer, frameWidth, ctx->videoPixelMode); int bufferSize = ctx->mediaengine->writeVideoImage(buffer, frameWidth, ctx->videoPixelMode);
gpu->InvalidateCache(buffer, bufferSize, GPU_INVALIDATE_SAFE); gpu->NotifyVideoUpload(buffer, bufferSize, frameWidth, ctx->videoPixelMode);
ctx->avc.avcFrameStatus = 1; ctx->avc.avcFrameStatus = 1;
ctx->videoFrameCount++; ctx->videoFrameCount++;
} else { } else {
@ -1872,7 +1872,8 @@ static u32 sceMpegAvcCsc(u32 mpeg, u32 sourceAddr, u32 rangeAddr, int frameWidth
int height = Memory::Read_U32(rangeAddr + 12); int height = Memory::Read_U32(rangeAddr + 12);
int destSize = ctx->mediaengine->writeVideoImageWithRange(destAddr, frameWidth, ctx->videoPixelMode, x, y, width, height); int destSize = ctx->mediaengine->writeVideoImageWithRange(destAddr, frameWidth, ctx->videoPixelMode, x, y, width, height);
gpu->InvalidateCache(destAddr, destSize, GPU_INVALIDATE_SAFE); gpu->NotifyVideoUpload(destAddr, destSize, frameWidth, ctx->videoPixelMode);
// Do not use avcDecodeDelayMs 's value // Do not use avcDecodeDelayMs 's value
// Will cause video 's screen dislocation in Bleach heat of soul 6 // Will cause video 's screen dislocation in Bleach heat of soul 6
// https://github.com/hrydgard/ppsspp/issues/5535 // https://github.com/hrydgard/ppsspp/issues/5535

View File

@ -1540,7 +1540,7 @@ static int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr)
int bufw = videoData->frameWidth == 0 ? 512 : videoData->frameWidth & ~1; int bufw = videoData->frameWidth == 0 ? 512 : videoData->frameWidth & ~1;
// Always write the video frame, even after the video has ended. // Always write the video frame, even after the video has ended.
int displaybufSize = psmfplayer->mediaengine->writeVideoImage(videoData->displaybuf, bufw, videoPixelMode); int displaybufSize = psmfplayer->mediaengine->writeVideoImage(videoData->displaybuf, bufw, videoPixelMode);
gpu->InvalidateCache(videoData->displaybuf, displaybufSize, GPU_INVALIDATE_SAFE); gpu->NotifyVideoUpload(videoData->displaybuf, displaybufSize, bufw, videoPixelMode);
__PsmfUpdatePts(psmfplayer, videoData); __PsmfUpdatePts(psmfplayer, videoData);
_PsmfPlayerFillRingbuffer(psmfplayer); _PsmfPlayerFillRingbuffer(psmfplayer);

View File

@ -799,7 +799,8 @@ int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int vid
delete [] imgbuf; delete [] imgbuf;
} }
return videoImageSize; // Account for the y offset as well.
return videoImageSize + videoLineSize * ypos;
#endif // USE_FFMPEG #endif // USE_FFMPEG
return 0; return 0;
} }

View File

@ -487,6 +487,26 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
return vfb; return vfb;
} }
void FramebufferManagerCommon::NotifyVideoUpload(u32 addr, int size, int width, GEBufferFormat fmt) {
// Note: UpdateFromMemory() is still called later.
// This is a special case where we have extra information prior to the invalidation.
// TODO: Could possibly be an offset...
VirtualFramebuffer *vfb = GetVFBAt(addr);
if (vfb) {
if (vfb->format != fmt || vfb->drawnFormat != fmt) {
DEBUG_LOG(ME, "Changing format for %08x from %d to %d", addr, vfb->drawnFormat, fmt);
vfb->format = fmt;
vfb->drawnFormat = fmt;
// Let's count this as a "render". This will also force us to use the correct format.
vfb->last_frame_render = gpuStats.numFlips;
}
// TODO: Check width?
}
}
void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) { void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) {
addr &= ~0x40000000; addr &= ~0x40000000;
// TODO: Could go through all FBOs, but probably not important? // TODO: Could go through all FBOs, but probably not important?

View File

@ -160,6 +160,7 @@ public:
virtual void RebindFramebuffer() = 0; virtual void RebindFramebuffer() = 0;
bool NotifyFramebufferCopy(u32 src, u32 dest, int size, bool isMemset, u32 skipDrawReason); bool NotifyFramebufferCopy(u32 src, u32 dest, int size, bool isMemset, u32 skipDrawReason);
void NotifyVideoUpload(u32 addr, int size, int width, GEBufferFormat fmt);
void UpdateFromMemory(u32 addr, int size, bool safe); void UpdateFromMemory(u32 addr, int size, bool safe);
virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) = 0; virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) = 0;
// Returns true if it's sure this is a direct FBO->FBO transfer and it has already handle it. // Returns true if it's sure this is a direct FBO->FBO transfer and it has already handle it.

View File

@ -862,6 +862,9 @@ namespace DX9 {
int w = std::min(pixels % vfb->fb_stride, (int)vfb->width); int w = std::min(pixels % vfb->fb_stride, (int)vfb->width);
int h = std::min((pixels + vfb->fb_stride - 1) / vfb->fb_stride, (int)vfb->height); int h = std::min((pixels + vfb->fb_stride - 1) / vfb->fb_stride, (int)vfb->height);
// We might still have a pending draw to the fb in question, flush if so.
FlushBeforeCopy();
// No need to download if we already have it. // No need to download if we already have it.
if (!vfb->memoryUpdated && vfb->clutUpdatedBytes < loadBytes) { if (!vfb->memoryUpdated && vfb->clutUpdatedBytes < loadBytes) {
// We intentionally don't call OptimizeDownloadRange() here - we don't want to over download. // We intentionally don't call OptimizeDownloadRange() here - we don't want to over download.

View File

@ -1952,6 +1952,13 @@ void DIRECTX9_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationTy
} }
} }
void DIRECTX9_GPU::NotifyVideoUpload(u32 addr, int size, int width, int format) {
if (Memory::IsVRAMAddress(addr)) {
framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format);
}
InvalidateCache(addr, size, GPU_INVALIDATE_SAFE);
}
void DIRECTX9_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { void DIRECTX9_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) {
if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) { if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) {
// We use a little hack for Download/Upload using a VRAM mirror. // We use a little hack for Download/Upload using a VRAM mirror.

View File

@ -48,6 +48,7 @@ public:
void BeginFrame() override; void BeginFrame() override;
void UpdateStats() override; void UpdateStats() override;
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
void NotifyVideoUpload(u32 addr, int size, int width, int format) override;
bool PerformMemoryCopy(u32 dest, u32 src, int size) override; bool PerformMemoryCopy(u32 dest, u32 src, int size) override;
bool PerformMemorySet(u32 dest, u8 v, int size) override; bool PerformMemorySet(u32 dest, u8 v, int size) override;
bool PerformMemoryDownload(u32 dest, int size) override; bool PerformMemoryDownload(u32 dest, int size) override;

View File

@ -1173,6 +1173,9 @@ void FramebufferManager::DownloadFramebufferForClut(u32 fb_address, u32 loadByte
int w = std::min(pixels % vfb->fb_stride, (int)vfb->width); int w = std::min(pixels % vfb->fb_stride, (int)vfb->width);
int h = std::min((pixels + vfb->fb_stride - 1) / vfb->fb_stride, (int)vfb->height); int h = std::min((pixels + vfb->fb_stride - 1) / vfb->fb_stride, (int)vfb->height);
// We might still have a pending draw to the fb in question, flush if so.
FlushBeforeCopy();
// No need to download if we already have it. // No need to download if we already have it.
if (!vfb->memoryUpdated && vfb->clutUpdatedBytes < loadBytes) { if (!vfb->memoryUpdated && vfb->clutUpdatedBytes < loadBytes) {
// We intentionally don't call OptimizeDownloadRange() here - we don't want to over download. // We intentionally don't call OptimizeDownloadRange() here - we don't want to over download.

View File

@ -2201,6 +2201,13 @@ void GLES_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType t
} }
} }
void GLES_GPU::NotifyVideoUpload(u32 addr, int size, int width, int format) {
if (Memory::IsVRAMAddress(addr)) {
framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format);
}
InvalidateCache(addr, size, GPU_INVALIDATE_SAFE);
}
void GLES_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { void GLES_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) {
if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) { if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) {
// We use a little hack for Download/Upload using a VRAM mirror. // We use a little hack for Download/Upload using a VRAM mirror.

View File

@ -52,6 +52,7 @@ public:
void BeginFrame() override; void BeginFrame() override;
void UpdateStats() override; void UpdateStats() override;
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
void NotifyVideoUpload(u32 addr, int size, int width, int format) override;
bool PerformMemoryCopy(u32 dest, u32 src, int size) override; bool PerformMemoryCopy(u32 dest, u32 src, int size) override;
bool PerformMemorySet(u32 dest, u8 v, int size) override; bool PerformMemorySet(u32 dest, u8 v, int size) override;
bool PerformMemoryDownload(u32 dest, int size) override; bool PerformMemoryDownload(u32 dest, int size) override;

View File

@ -253,6 +253,7 @@ public:
// Invalidate any cached content sourced from the specified range. // Invalidate any cached content sourced from the specified range.
// If size = -1, invalidate everything. // If size = -1, invalidate everything.
virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type) = 0; virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type) = 0;
virtual void NotifyVideoUpload(u32 addr, int size, int width, int format) = 0;
// Update either RAM from VRAM, or VRAM from RAM... or even VRAM from VRAM. // Update either RAM from VRAM, or VRAM from RAM... or even VRAM from VRAM.
virtual bool PerformMemoryCopy(u32 dest, u32 src, int size) = 0; virtual bool PerformMemoryCopy(u32 dest, u32 src, int size) = 0;
virtual bool PerformMemorySet(u32 dest, u8 v, int size) = 0; virtual bool PerformMemorySet(u32 dest, u8 v, int size) = 0;

View File

@ -687,6 +687,10 @@ void NullGPU::InvalidateCache(u32 addr, int size, GPUInvalidationType type) {
// Nothing to invalidate. // Nothing to invalidate.
} }
void NullGPU::NotifyVideoUpload(u32 addr, int size, int width, int format) {
// Nothing to do.
}
bool NullGPU::PerformMemoryCopy(u32 dest, u32 src, int size) { bool NullGPU::PerformMemoryCopy(u32 dest, u32 src, int size) {
// Nothing to update. // Nothing to update.
InvalidateCache(dest, size, GPU_INVALIDATE_HINT); InvalidateCache(dest, size, GPU_INVALIDATE_HINT);

View File

@ -34,6 +34,7 @@ public:
void CopyDisplayToOutput() override {} void CopyDisplayToOutput() override {}
void UpdateStats() override; void UpdateStats() override;
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
void NotifyVideoUpload(u32 addr, int size, int width, int format) override;
bool PerformMemoryCopy(u32 dest, u32 src, int size) override; bool PerformMemoryCopy(u32 dest, u32 src, int size) override;
bool PerformMemorySet(u32 dest, u8 v, int size) override; bool PerformMemorySet(u32 dest, u8 v, int size) override;
bool PerformMemoryDownload(u32 dest, int size) override; bool PerformMemoryDownload(u32 dest, int size) override;

View File

@ -873,6 +873,11 @@ void SoftGPU::InvalidateCache(u32 addr, int size, GPUInvalidationType type)
// Nothing to invalidate. // Nothing to invalidate.
} }
void SoftGPU::NotifyVideoUpload(u32 addr, int size, int width, int format)
{
// Ignore.
}
bool SoftGPU::PerformMemoryCopy(u32 dest, u32 src, int size) bool SoftGPU::PerformMemoryCopy(u32 dest, u32 src, int size)
{ {
// Nothing to update. // Nothing to update.

View File

@ -58,6 +58,7 @@ public:
void CopyDisplayToOutput() override; void CopyDisplayToOutput() override;
void UpdateStats() override; void UpdateStats() override;
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
void NotifyVideoUpload(u32 addr, int size, int width, int format) override;
bool PerformMemoryCopy(u32 dest, u32 src, int size) override; bool PerformMemoryCopy(u32 dest, u32 src, int size) override;
bool PerformMemorySet(u32 dest, u8 v, int size) override; bool PerformMemorySet(u32 dest, u8 v, int size) override;
bool PerformMemoryDownload(u32 dest, int size) override; bool PerformMemoryDownload(u32 dest, int size) override;

View File

@ -55,7 +55,7 @@ extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV;
typedef void (EGLAPIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) ( typedef void (EGLAPIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) (
GLint srcX0, GLint srcY0, GLint srcX1, GLuint srcY1, GLint srcX0, GLint srcY0, GLint srcX1, GLuint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLuint dstY1, GLint dstX0, GLint dstY0, GLint dstX1, GLuint dstY1,
GLint mask, GLenum filter); GLbitfield mask, GLenum filter);
#endif #endif
extern PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV; extern PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV;