Files
renderdoc/qrenderdoc/Windows/TextureViewer.cpp
T
baldurk c539510da8 Only flip uncompressed texture data out of GL when saving to disk
* When transferring over the network, we keep texture data consistently
  in GL origin-bottom-left order. This means we can just flip images on
  display and otherwise have things consistently behaving, while still
  preserving the behaviour of flipping on saving to disk to try and
  mostly 'do the right thing' when saving an image.
* The behaviour should be the same as before except for remote proxying
  which is fixed. The behaviour for GL is still that compressed images
  saved as compressed will appear to flip vertically from what is
  natively displayed in the UI, but I think this is the only sensible
  way to behave (and anyway, flipping compressed images is far too
  involved to be worthwhile).
2016-08-24 15:53:59 +02:00

288 lines
8.8 KiB
C++

#if defined(__linux__)
#define RENDERDOC_WINDOWING_XLIB 1
#define RENDERDOC_WINDOWING_XCB 1
#endif
#include "TextureViewer.h"
#include "Code/Core.h"
#include "FlowLayout.h"
#include "ui_TextureViewer.h"
#if defined(__linux__)
#include <GL/glx.h>
#include <X11/Xlib.h>
#include <xcb/xcb.h>
#include <QX11Info>
#endif
TextureViewer::TextureViewer(Core *core, QWidget *parent)
: QFrame(parent), ui(new Ui::TextureViewer), m_Core(core)
{
ui->setupUi(this);
m_Core->AddLogViewer(this);
ui->render->SetOutput(NULL);
ui->pixelContext->SetOutput(NULL);
m_Output = NULL;
QWidget *renderContainer = ui->renderContainer;
QObject::connect(ui->render, &CustomPaintWidget::clicked, this, &TextureViewer::on_render_clicked);
QObject::connect(ui->render, &CustomPaintWidget::mouseMove, this,
&TextureViewer::on_render_clicked);
ui->dockarea->addToolWindow(ui->renderContainer, ToolWindowManager::EmptySpace);
ui->dockarea->setToolWindowProperties(renderContainer, ToolWindowManager::DisallowUserDocking |
ToolWindowManager::HideCloseButton |
ToolWindowManager::DisableDraggableTab);
ToolWindowManager::AreaReference ref(ToolWindowManager::AddTo,
ui->dockarea->areaOf(renderContainer));
/*
QWidget *lockedTabTest = new QWidget(this);
lockedTabTest->setWindowTitle(tr("Locked Tab #1"));
ui->dockarea->addToolWindow(lockedTabTest, ref);
ui->dockarea->setToolWindowProperties(lockedTabTest, ToolWindowManager::DisallowUserDocking |
ToolWindowManager::HideCloseButton);
lockedTabTest = new QWidget(this);
lockedTabTest->setWindowTitle(tr("Locked Tab #2"));
ui->dockarea->addToolWindow(lockedTabTest, ref);
ui->dockarea->setToolWindowProperties(lockedTabTest, ToolWindowManager::DisallowUserDocking |
ToolWindowManager::HideCloseButton);
lockedTabTest = new QWidget(this);
lockedTabTest->setWindowTitle(tr("Locked Tab #3"));
ui->dockarea->addToolWindow(lockedTabTest, ref);
ui->dockarea->setToolWindowProperties(lockedTabTest, ToolWindowManager::DisallowUserDocking |
ToolWindowManager::HideCloseButton);
lockedTabTest = new QWidget(this);
lockedTabTest->setWindowTitle(tr("Locked Tab #4"));
ui->dockarea->addToolWindow(lockedTabTest, ref);
ui->dockarea->setToolWindowProperties(lockedTabTest, ToolWindowManager::DisallowUserDocking |
ToolWindowManager::HideCloseButton);*/
ui->dockarea->addToolWindow(
ui->resourceThumbs, ToolWindowManager::AreaReference(ToolWindowManager::RightOf,
ui->dockarea->areaOf(renderContainer)));
ui->dockarea->setToolWindowProperties(ui->resourceThumbs, ToolWindowManager::HideCloseButton);
ui->dockarea->addToolWindow(
ui->targetThumbs, ToolWindowManager::AreaReference(ToolWindowManager::AddTo,
ui->dockarea->areaOf(ui->resourceThumbs)));
ui->dockarea->setToolWindowProperties(ui->targetThumbs, ToolWindowManager::HideCloseButton);
// need to add a way to make this less than 50% programmatically
ui->dockarea->addToolWindow(ui->pixelContextLayout, ToolWindowManager::AreaReference(
ToolWindowManager::BottomOf,
ui->dockarea->areaOf(ui->targetThumbs)));
ui->dockarea->setToolWindowProperties(ui->pixelContextLayout, ToolWindowManager::HideCloseButton);
ui->dockarea->setAllowFloatingWindow(false);
ui->dockarea->setRubberBandLineWidth(50);
renderContainer->setWindowTitle(tr("OM RenderTarget 0 - GBuffer Colour"));
ui->pixelContextLayout->setWindowTitle(tr("Pixel Context"));
ui->targetThumbs->setWindowTitle(tr("OM Targets"));
ui->resourceThumbs->setWindowTitle(tr("PS Resources"));
QVBoxLayout *vertical = new QVBoxLayout(this);
vertical->setSpacing(3);
vertical->setContentsMargins(0, 0, 0, 0);
QWidget *flow1widget = new QWidget(this);
QWidget *flow2widget = new QWidget(this);
FlowLayout *flow1 = new FlowLayout(flow1widget, 0, 3, 3);
FlowLayout *flow2 = new FlowLayout(flow2widget, 0, 3, 3);
flow1widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
flow2widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
flow1->addWidget(ui->channelsToolbar);
flow1->addWidget(ui->subresourceToolbar);
flow1->addWidget(ui->actionToolbar);
flow2->addWidget(ui->zoomToolbar);
flow2->addWidget(ui->overlayToolbar);
flow2->addWidget(ui->rangeToolbar);
vertical->addWidget(flow1widget);
vertical->addWidget(flow2widget);
vertical->addWidget(ui->dockarea);
Ui_TextureViewer *u = ui;
u->pixelcontextgrid->setAlignment(u->pushButton, Qt::AlignCenter);
u->pixelcontextgrid->setAlignment(u->pushButton_2, Qt::AlignCenter);
}
TextureViewer::~TextureViewer()
{
m_Core->RemoveLogViewer(this);
delete ui;
}
void TextureViewer::on_render_clicked(QMouseEvent *e)
{
uint32_t x = (uint32_t)e->x();
uint32_t y = (uint32_t)e->y();
if(e->buttons() & Qt::RightButton)
{
m_Core->Renderer()->AsyncInvoke([this, x, y](IReplayRenderer *) {
ResourceId id = m_TexDisplay.texid;
PixelValue val;
ReplayOutput_PickPixel(m_Output, id, false, x, y, 0, 0, 0, &val);
QString str = QString("Pixel %1 %2 %3 %4")
.arg(val.value_f[0])
.arg(val.value_f[1])
.arg(val.value_f[2])
.arg(val.value_f[3]);
GUIInvoke::call([this, str, val]() {
ui->statusText->setText(str);
QPalette Pal(palette());
// set black background
Pal.setColor(
QPalette::Background,
QColor(int(val.value_f[0] * 255), int(val.value_f[1] * 255), int(val.value_f[2] * 255)));
ui->pickSwatch->setAutoFillBackground(true);
ui->pickSwatch->setPalette(Pal);
});
});
}
}
void TextureViewer::OnLogfileLoaded()
{
#if defined(WIN32)
WindowingSystem system = eWindowingSystem_Win32;
HWND wnd = (HWND)ui->render->winId();
#elif defined(__linux__)
XCBWindowData xcb = {
QX11Info::connection(), (xcb_window_t)ui->render->winId(),
};
XlibWindowData xlib = {QX11Info::display(), (Drawable)ui->render->winId()};
rdctype::array<WindowingSystem> systems;
m_Core->Renderer()->BlockInvoke(
[&systems](IReplayRenderer *r) { r->GetSupportedWindowSystems(&systems); });
WindowingSystem system = eWindowingSystem_Unknown;
void *wnd = NULL;
// prefer XCB
for(int32_t i = 0; i < systems.count; i++)
{
if(systems[i] == eWindowingSystem_XCB)
{
system = eWindowingSystem_XCB;
wnd = &xcb;
break;
}
}
for(int32_t i = 0; wnd == NULL && i < systems.count; i++)
{
if(systems[i] == eWindowingSystem_Xlib)
{
system = eWindowingSystem_Xlib;
wnd = &xlib;
break;
}
}
#else
#error "Unknown platform"
#endif
m_Core->Renderer()->BlockInvoke([system, wnd, this](IReplayRenderer *r) {
m_Output = r->CreateOutput(system, wnd, eOutputType_TexDisplay);
ui->render->SetOutput(m_Output);
OutputConfig c = {eOutputType_TexDisplay};
m_Output->SetOutputConfig(c);
});
}
void TextureViewer::OnLogfileClosed()
{
m_Output = NULL;
ui->render->SetOutput(NULL);
}
void TextureViewer::OnEventSelected(uint32_t eventID)
{
m_Core->Renderer()->AsyncInvoke([this](IReplayRenderer *) {
TextureDisplay &d = m_TexDisplay;
if(m_Core->APIProps().pipelineType == eGraphicsAPI_D3D11)
{
d.texid = m_Core->CurD3D11PipelineState.m_OM.RenderTargets[0].Resource;
}
else if(m_Core->APIProps().pipelineType == eGraphicsAPI_OpenGL)
{
d.texid = m_Core->CurGLPipelineState.m_FB.m_DrawFBO.Color[0].Obj;
}
else
{
const VulkanPipelineState &pipe = m_Core->CurVulkanPipelineState;
if(pipe.Pass.renderpass.colorAttachments.count > 0)
d.texid = pipe.Pass.framebuffer.attachments[pipe.Pass.renderpass.colorAttachments[0]].img;
if(d.texid == ResourceId())
{
const FetchDrawcall *draw = m_Core->CurDrawcall();
if(draw)
d.texid = draw->copyDestination;
}
}
d.mip = 0;
d.sampleIdx = ~0U;
d.overlay = eTexOverlay_None;
d.CustomShader = ResourceId();
d.HDRMul = -1.0f;
d.linearDisplayAsGamma = true;
d.FlipY = false;
d.rangemin = 0.0f;
d.rangemax = 1.0f;
d.scale = -1.0f;
d.offx = 0.0f;
d.offy = 0.0f;
d.sliceFace = 0;
d.rawoutput = false;
d.lightBackgroundColour = d.darkBackgroundColour = FloatVector(0.0f, 0.0f, 0.0f, 0.0f);
d.Red = d.Green = d.Blue = true;
d.Alpha = false;
m_Output->SetTextureDisplay(d);
FetchTexture *tex = m_Core->GetTexture(d.texid);
GUIInvoke::call([this, tex]() {
if(tex)
ui->renderContainer->setWindowTitle(tr(tex->name.elems));
ui->render->update();
});
});
}