Skip to content

Commit

Permalink
libgui|GLState|Canvas: Viewport is now part of the GL state
Browse files Browse the repository at this point in the history
Notable change: the topmost GLState on the stack is now applied
automatically when a Canvas is drawn. The future implication is that
the client's initial GL state for a frame needs to be on the GL state
stack.
  • Loading branch information
skyjake committed Apr 26, 2013
1 parent c380fee commit c0a7242
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 31 deletions.
6 changes: 6 additions & 0 deletions doomsday/libgui/include/de/gui/glstate.h
Expand Up @@ -24,6 +24,7 @@
#define LIBGUI_GLSTATE_H

#include <de/libdeng2.h>
#include <de/Rectangle>
#include <utility>

#include "libgui.h"
Expand Down Expand Up @@ -82,6 +83,9 @@ namespace gl
* drawing. GLState::apply() can be called for any GLState instance to use it
* as the current GL state.
*
* @note The default viewport is (0,0)&rarr;(0,0). The viewport has to be set
* when the desired size is known (for instance when a Canvas is resized).
*
* @ingroup gl
*/
class LIBGUI_PUBLIC GLState
Expand All @@ -104,6 +108,7 @@ class LIBGUI_PUBLIC GLState
void setBlendOp(gl::BlendOp op);
void setTarget(GLTarget &target);
void setDefaultTarget();
void setViewport(Rectangleui const &viewportRect);

gl::Cull cull() const;
bool depthTest() const;
Expand All @@ -115,6 +120,7 @@ class LIBGUI_PUBLIC GLState
gl::BlendFunc blendFunc() const;
gl::BlendOp blendOp() const;
GLTarget &target() const;
Rectangleui viewport() const;

/**
* Updates the OpenGL state to match this GLState. Until this is called no
Expand Down
4 changes: 4 additions & 0 deletions doomsday/libgui/src/canvas.cpp
Expand Up @@ -19,6 +19,7 @@

#include "de/Canvas"
#include "de/CanvasWindow"
#include "de/GLState"
#include "de/gui/opengl.h"

#include <de/App>
Expand Down Expand Up @@ -298,6 +299,9 @@ void Canvas::notifyReady()

void Canvas::paintGL()
{
// Make sure any changes to the state stack become effective.
GLState::top().apply();

DENG2_FOR_AUDIENCE(GLDraw, i) i->canvasGLDraw(*this);
}

Expand Down
4 changes: 2 additions & 2 deletions doomsday/libgui/src/displaymode_windows.cpp
Expand Up @@ -116,7 +116,7 @@ int DisplayMode_Native_Change(const DisplayMode* mode, int shouldCapture)

void DisplayMode_Native_SetColorTransfer(DisplayColorTransfer const *colors)
{
HWND hWnd = (HWND) de::PersistentCanvasWindow::main().nativeHandle();
HWND hWnd = (HWND) de::CanvasWindow::main().nativeHandle();
DENG2_ASSERT(hWnd != 0);

HDC hDC = GetDC(hWnd);
Expand All @@ -129,7 +129,7 @@ void DisplayMode_Native_SetColorTransfer(DisplayColorTransfer const *colors)

void DisplayMode_Native_GetColorTransfer(DisplayColorTransfer *colors)
{
HWND hWnd = (HWND) de::PersistentCanvasWindow::main().nativeHandle();
HWND hWnd = (HWND) de::CanvasWindow::main().nativeHandle();
DENG2_ASSERT(hWnd != 0);

HDC hDC = GetDC(hWnd);
Expand Down
100 changes: 74 additions & 26 deletions doomsday/libgui/src/glstate.cpp
Expand Up @@ -38,6 +38,10 @@ namespace internal
BlendFuncSrc,
BlendFuncDest,
BlendOp,
ViewportX,
ViewportY,
ViewportWidth,
ViewportHeight,
MAX_PROPERTIES
};

Expand Down Expand Up @@ -66,20 +70,26 @@ DENG2_PIMPL(GLState)
Instance(Public *i) : Base(i), target(0)
{
static BitField::Spec const propSpecs[MAX_PROPERTIES] = {
{ CullMode, 2 },
{ DepthTest, 1 },
{ DepthFunc, 3 },
{ DepthWrite, 1 },
{ Blend, 1 },
{ BlendFuncSrc, 4 },
{ BlendFuncDest, 4 },
{ BlendOp, 2 }
{ CullMode, 2 },
{ DepthTest, 1 },
{ DepthFunc, 3 },
{ DepthWrite, 1 },
{ Blend, 1 },
{ BlendFuncSrc, 4 },
{ BlendFuncDest, 4 },
{ BlendOp, 2 },
{ ViewportX, 12 }, // 4096 max
{ ViewportY, 12 }, // 4096 max
{ ViewportWidth, 12 }, // 4096 max
{ ViewportHeight, 12 } // 4096 max
};
props.addElements(propSpecs, MAX_PROPERTIES);
}

Instance(Public *i, Instance const &other)
: Base(i), props(other.props), target(other.target)
: Base(i),
props(other.props),
target(other.target)
{}

static GLenum glComp(gl::Comparison comp)
Expand Down Expand Up @@ -182,10 +192,37 @@ DENG2_PIMPL(GLState)
}
break;

case ViewportX:
case ViewportY:
case ViewportWidth:
case ViewportHeight:
{
Rectangleui vp = self.viewport();
glViewport(vp.left(), vp.top(), vp.width(), vp.height());
break;
}

default:
break;
}
}

void removeRedundancies(BitField::Ids &changed)
{
if(changed.contains(BlendFuncSrc) && changed.contains(BlendFuncDest))
{
changed.remove(BlendFuncDest);
}

if(changed.contains(ViewportX) || changed.contains(ViewportY) ||
changed.contains(ViewportWidth) || changed.contains(ViewportHeight))
{
changed.insert(ViewportX);
changed.remove(ViewportY);
changed.remove(ViewportWidth);
changed.remove(ViewportHeight);
}
}
};

GLState::GLState() : d(new Instance(this))
Expand Down Expand Up @@ -256,6 +293,14 @@ void GLState::setDefaultTarget()
d->target = 0;
}

void GLState::setViewport(Rectangleui const &viewportRect)
{
d->props.set(ViewportX, viewportRect.left());
d->props.set(ViewportY, viewportRect.top());
d->props.set(ViewportWidth, viewportRect.width());
d->props.set(ViewportHeight, viewportRect.height());
}

gl::Cull GLState::cull() const
{
return d->props.valueAs<gl::Cull>(CullMode);
Expand Down Expand Up @@ -307,13 +352,29 @@ GLTarget &GLState::target() const
{
return *d->target;
}
return PersistentCanvasWindow::main().canvas().renderTarget();
return CanvasWindow::main().canvas().renderTarget();
}

Rectangleui GLState::viewport() const
{
return Rectangleui(d->props[ViewportX],
d->props[ViewportY],
d->props[ViewportWidth],
d->props[ViewportHeight]);
}

void GLState::apply() const
{
BitField::Ids changed;
// Update the render target.
if(currentTarget != d->target)
{
if(currentTarget) currentTarget->glRelease();
currentTarget = d->target;
if(currentTarget) currentTarget->glBind();
}

// Determine which properties have changed.
BitField::Ids changed;
if(!currentProps.size())
{
// Apply everything.
Expand All @@ -327,27 +388,14 @@ void GLState::apply() const

if(!changed.isEmpty())
{
currentProps = d->props;

// The blend func only needs to be set once.
if(changed.contains(BlendFuncSrc) && changed.contains(BlendFuncDest))
{
changed.remove(BlendFuncDest);
}
d->removeRedundancies(changed);

// Apply the changed properties.
foreach(BitField::Id id, changed)
{
d->glApply(Property(id));
}
}

// Update the render target.
if(currentTarget != d->target)
{
if(currentTarget) currentTarget->glRelease();
currentTarget = d->target;
if(currentTarget) currentTarget->glBind();
currentProps = d->props;
}
}

Expand Down
6 changes: 3 additions & 3 deletions doomsday/libgui/src/gltarget.cpp
Expand Up @@ -22,7 +22,7 @@
#include "de/GLTarget"
#include "de/GLTexture"
#include "de/GLState"
#include "de/PersistentCanvasWindow"
#include "de/CanvasWindow"
#include <de/Asset>

namespace de {
Expand Down Expand Up @@ -212,7 +212,7 @@ QImage GLTarget::toImage() const
{
if(!d->fbo)
{
return PersistentCanvasWindow::main().canvas().grabImage();
return CanvasWindow::main().canvas().grabImage();
}
else if(d->flags & Color)
{
Expand Down Expand Up @@ -265,7 +265,7 @@ GLTarget::Size GLTarget::size() const
{
return d->size;
}
return PersistentCanvasWindow::main().canvas().size();
return CanvasWindow::main().canvas().size();
}

} // namespace de

0 comments on commit c0a7242

Please sign in to comment.