Add an interface to return the current framebuffer.
This commit is contained in:
parent
2ad5167f75
commit
6af44910c1
7 changed files with 140 additions and 1 deletions
|
@ -30,6 +30,93 @@ struct GPUDebugOp {
|
||||||
std::string desc;
|
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 {
|
class GPUDebugInterface {
|
||||||
public:
|
public:
|
||||||
virtual bool GetCurrentDisplayList(DisplayList &list) = 0;
|
virtual bool GetCurrentDisplayList(DisplayList &list) = 0;
|
||||||
|
@ -49,6 +136,13 @@ public:
|
||||||
virtual u32 GetIndexAddress() = 0;
|
virtual u32 GetIndexAddress() = 0;
|
||||||
virtual GPUgstate GetGState() = 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:
|
// TODO:
|
||||||
// cached framebuffers / textures / vertices?
|
// cached framebuffers / textures / vertices?
|
||||||
// get content of framebuffer / texture
|
// get content of framebuffer / texture
|
||||||
|
|
|
@ -1310,3 +1310,28 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size) {
|
||||||
void FramebufferManager::Resized() {
|
void FramebufferManager::Resized() {
|
||||||
resized_ = true;
|
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);
|
void DestroyFramebuf(VirtualFramebuffer *vfb);
|
||||||
|
|
||||||
|
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CompileDraw2DProgram();
|
void CompileDraw2DProgram();
|
||||||
|
|
||||||
|
|
|
@ -1504,3 +1504,8 @@ void GLES_GPU::DoState(PointerWrap &p) {
|
||||||
gstate_c.textureChanged = true;
|
gstate_c.textureChanged = true;
|
||||||
framebufferManager_.DestroyAllFBOs();
|
framebufferManager_.DestroyAllFBOs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GLES_GPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer)
|
||||||
|
{
|
||||||
|
return framebufferManager_.GetCurrentFramebuffer(buffer);
|
||||||
|
}
|
||||||
|
|
|
@ -66,6 +66,8 @@ public:
|
||||||
}
|
}
|
||||||
std::vector<FramebufferInfo> GetFramebufferList();
|
std::vector<FramebufferInfo> GetFramebufferList();
|
||||||
|
|
||||||
|
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void FastRunLoop(DisplayList &list);
|
virtual void FastRunLoop(DisplayList &list);
|
||||||
virtual void ProcessEvent(GPUEvent ev);
|
virtual void ProcessEvent(GPUEvent ev);
|
||||||
|
|
|
@ -743,3 +743,11 @@ void SoftGPU::UpdateMemory(u32 dest, u32 src, int size)
|
||||||
// Nothing to update.
|
// Nothing to update.
|
||||||
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
|
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
|
#pragma once
|
||||||
|
|
||||||
#include "../GPUCommon.h"
|
#include "GPU/GPUCommon.h"
|
||||||
|
#include "GPU/Common/GPUDebugInterface.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
|
@ -72,6 +73,8 @@ public:
|
||||||
fullInfo = "Software";
|
fullInfo = "Software";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool GetCurrentFramebuffer(GPUDebugBuffer &buffer);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void FastRunLoop(DisplayList &list);
|
virtual void FastRunLoop(DisplayList &list);
|
||||||
virtual void ProcessEvent(GPUEvent ev);
|
virtual void ProcessEvent(GPUEvent ev);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue