mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-27 07:20:49 +00:00
Add an interface to return the current framebuffer.
This commit is contained in:
parent
2ad5167f75
commit
6af44910c1
@ -30,6 +30,93 @@ struct GPUDebugOp {
|
||||
std::string desc;
|
||||
};
|
||||
|
||||
struct GPUDebugBuffer {
|
||||
GPUDebugBuffer() : alloc_(false), data_(NULL) {
|
||||
}
|
||||
|
||||
GPUDebugBuffer(void *data, u32 stride, u32 height, GEBufferFormat fmt)
|
||||
: alloc_(false), data_((u8 *)data), stride_(stride), height_(height), fmt_(fmt) {
|
||||
}
|
||||
|
||||
GPUDebugBuffer(GPUDebugBuffer &&other) {
|
||||
alloc_ = other.alloc_;
|
||||
data_ = other.data_;
|
||||
height_ = other.height_;
|
||||
stride_ = other.stride_;
|
||||
fmt_ = other.fmt_;
|
||||
other.alloc_ = false;
|
||||
other.data_ = NULL;
|
||||
}
|
||||
|
||||
~GPUDebugBuffer() {
|
||||
Free();
|
||||
}
|
||||
|
||||
GPUDebugBuffer &operator = (GPUDebugBuffer &&other) {
|
||||
if (this != &other) {
|
||||
Free();
|
||||
alloc_ = other.alloc_;
|
||||
data_ = other.data_;
|
||||
height_ = other.height_;
|
||||
stride_ = other.stride_;
|
||||
fmt_ = other.fmt_;
|
||||
other.alloc_ = false;
|
||||
other.data_ = NULL;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Allocate(u32 stride, u32 height, GEBufferFormat fmt) {
|
||||
if (alloc_ && stride_ == stride && height_ == height && fmt_ == fmt) {
|
||||
// Already allocated the right size.
|
||||
return;
|
||||
}
|
||||
|
||||
Free();
|
||||
alloc_ = true;
|
||||
height_ = height;
|
||||
stride_ = stride;
|
||||
fmt_ = fmt;
|
||||
|
||||
u32 pixelSize = 2;
|
||||
if (fmt == GE_FORMAT_8888) {
|
||||
pixelSize = 4;
|
||||
};
|
||||
|
||||
data_ = new u8[pixelSize * stride * height];
|
||||
}
|
||||
|
||||
void Free() {
|
||||
if (alloc_ && data_ != NULL) {
|
||||
delete [] data_;
|
||||
}
|
||||
data_ = NULL;
|
||||
}
|
||||
|
||||
u8 *GetData() const {
|
||||
return data_;
|
||||
}
|
||||
|
||||
u32 GetHeight() const {
|
||||
return height_;
|
||||
}
|
||||
|
||||
u32 GetStride() const {
|
||||
return stride_;
|
||||
}
|
||||
|
||||
GEBufferFormat GetFormat() const {
|
||||
return fmt_;
|
||||
}
|
||||
|
||||
bool alloc_;
|
||||
u8 *data_;
|
||||
u32 height_;
|
||||
u32 stride_;
|
||||
GEBufferFormat fmt_;
|
||||
};
|
||||
|
||||
class GPUDebugInterface {
|
||||
public:
|
||||
virtual bool GetCurrentDisplayList(DisplayList &list) = 0;
|
||||
@ -49,6 +136,13 @@ public:
|
||||
virtual u32 GetIndexAddress() = 0;
|
||||
virtual GPUgstate GetGState() = 0;
|
||||
|
||||
// Needs to be called from the GPU thread, so on the same thread as a notification is fine.
|
||||
// Calling from a separate thread (e.g. UI) may fail.
|
||||
virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer) {
|
||||
// False means unsupported.
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// cached framebuffers / textures / vertices?
|
||||
// get content of framebuffer / texture
|
||||
|
@ -1310,3 +1310,28 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size) {
|
||||
void FramebufferManager::Resized() {
|
||||
resized_ = true;
|
||||
}
|
||||
|
||||
bool FramebufferManager::GetCurrentFramebuffer(GPUDebugBuffer &buffer)
|
||||
{
|
||||
u32 fb_address = (gstate.fbptr & 0xFFFFFF) | ((gstate.fbwidth & 0xFF0000) << 8);
|
||||
int fb_stride = gstate.fbwidth & 0x3C0;
|
||||
|
||||
VirtualFramebuffer *vfb = currentRenderVfb_;
|
||||
if (!vfb) {
|
||||
vfb = GetVFBAt(fb_address);
|
||||
}
|
||||
|
||||
if (!vfb) {
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, gstate.FrameBufFormat());
|
||||
return true;
|
||||
}
|
||||
|
||||
buffer.Allocate(vfb->fb_stride, vfb->height, GE_FORMAT_8888);
|
||||
|
||||
fbo_bind_for_read(vfb->fbo);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||
glReadPixels(0, 0, vfb->fb_stride, vfb->height, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -170,6 +170,8 @@ public:
|
||||
|
||||
void DestroyFramebuf(VirtualFramebuffer *vfb);
|
||||
|
||||
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer);
|
||||
|
||||
private:
|
||||
void CompileDraw2DProgram();
|
||||
|
||||
|
@ -1504,3 +1504,8 @@ void GLES_GPU::DoState(PointerWrap &p) {
|
||||
gstate_c.textureChanged = true;
|
||||
framebufferManager_.DestroyAllFBOs();
|
||||
}
|
||||
|
||||
bool GLES_GPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer)
|
||||
{
|
||||
return framebufferManager_.GetCurrentFramebuffer(buffer);
|
||||
}
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
}
|
||||
std::vector<FramebufferInfo> GetFramebufferList();
|
||||
|
||||
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer);
|
||||
|
||||
protected:
|
||||
virtual void FastRunLoop(DisplayList &list);
|
||||
virtual void ProcessEvent(GPUEvent ev);
|
||||
|
@ -743,3 +743,11 @@ void SoftGPU::UpdateMemory(u32 dest, u32 src, int size)
|
||||
// Nothing to update.
|
||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
||||
}
|
||||
|
||||
bool SoftGPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer)
|
||||
{
|
||||
// We don't know the height, so just use 512, which should be the max (hopefully?)
|
||||
// TODO: Could check clipping and such, though...?
|
||||
buffer = GPUDebugBuffer(fb.data, gstate.FrameBufStride(), 512, gstate.FrameBufFormat());
|
||||
return true;
|
||||
}
|
||||
|
@ -17,7 +17,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../GPUCommon.h"
|
||||
#include "GPU/GPUCommon.h"
|
||||
#include "GPU/Common/GPUDebugInterface.h"
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
@ -72,6 +73,8 @@ public:
|
||||
fullInfo = "Software";
|
||||
}
|
||||
|
||||
virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer);
|
||||
|
||||
protected:
|
||||
virtual void FastRunLoop(DisplayList &list);
|
||||
virtual void ProcessEvent(GPUEvent ev);
|
||||
|
Loading…
Reference in New Issue
Block a user