winrt: Refactor backing store
Thanks to new features in ANGLE, the backing store implementation complexity can be greatly reduced. By using ES3 framebuffer blit, no shader code is required, and the shader loading code and blit shader can be removed. Change-Id: Iab3d915e279ad6468a75ef6257794f12acd8cb65 Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
This commit is contained in:
parent
1a9701fe81
commit
c7abf81786
@ -1,14 +0,0 @@
|
||||
uniform SamplerState Sampler : register(s0);
|
||||
uniform Texture2D Texture : register(t0);
|
||||
|
||||
void blitvs(in float4 pos0 : TEXCOORD0, in float2 tex0 : TEXCOORD1,
|
||||
out float4 gl_Position : SV_POSITION, out float2 coord : TEXCOORD0)
|
||||
{
|
||||
coord = tex0;
|
||||
gl_Position = pos0 * float4(1.0, -1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
float4 blitps(in float4 gl_Position : SV_POSITION, in float2 coord : TEXCOORD0) : SV_TARGET0
|
||||
{
|
||||
return Texture.Sample(Sampler, coord);
|
||||
}
|
@ -45,343 +45,136 @@
|
||||
#include "qwinrtwindow.h"
|
||||
#include "qwinrteglcontext.h"
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QOpenGLFramebufferObject>
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
// Generated shader headers
|
||||
#include "blitps.h"
|
||||
#include "blitvs.h"
|
||||
|
||||
namespace { // Utility namespace for writing out an ANGLE-compatible binary blob
|
||||
|
||||
// Must match packaged ANGLE
|
||||
enum : quint32 {
|
||||
AngleMajorVersion = 1,
|
||||
AngleMinorVersion = 3
|
||||
};
|
||||
|
||||
struct ShaderString
|
||||
{
|
||||
ShaderString(const char *data = 0) : data(data) { }
|
||||
const char *data;
|
||||
};
|
||||
|
||||
// ANGLE stream compatibility - when size_t is 32-bit, QDataStream::writeBytes() also works
|
||||
QDataStream &operator<<(QDataStream &stream, const ShaderString &shaderString)
|
||||
{
|
||||
if (!shaderString.data)
|
||||
return stream << size_t(0);
|
||||
|
||||
size_t len = strlen(shaderString.data);
|
||||
stream << len;
|
||||
stream.writeRawData(shaderString.data, int(len));
|
||||
return stream;
|
||||
}
|
||||
|
||||
struct Attribute
|
||||
{
|
||||
Attribute(GLenum type = 0, const char *name = 0, quint32 index = 0)
|
||||
: type(type), name(name), index(index) { }
|
||||
GLenum type;
|
||||
ShaderString name;
|
||||
quint32 index;
|
||||
};
|
||||
|
||||
struct Sampler
|
||||
{
|
||||
enum TextureType { Texture2D, TextureCube };
|
||||
Sampler(bool active = false, GLint unit = 0, TextureType type = Texture2D)
|
||||
: active(active), unit(unit), type(type) { }
|
||||
bool active;
|
||||
GLint unit;
|
||||
TextureType type;
|
||||
};
|
||||
|
||||
struct Uniform
|
||||
{
|
||||
Uniform() { }
|
||||
Uniform(GLenum type, quint32 precision, const char *name, quint32 arraySize,
|
||||
quint32 psRegisterIndex, quint32 vsRegisterIndex, quint32 registerCount)
|
||||
: type(type), precision(precision), name(name), arraySize(arraySize)
|
||||
, psRegisterIndex(psRegisterIndex), vsRegisterIndex(vsRegisterIndex), registerCount(registerCount) { }
|
||||
GLenum type;
|
||||
quint32 precision;
|
||||
ShaderString name;
|
||||
quint32 arraySize;
|
||||
quint32 psRegisterIndex;
|
||||
quint32 vsRegisterIndex;
|
||||
quint32 registerCount;
|
||||
};
|
||||
|
||||
struct UniformIndex
|
||||
{
|
||||
UniformIndex(const char *name = 0, quint32 element = 0, quint32 index = 0)
|
||||
: name(name), element(element), index(index) { }
|
||||
ShaderString name;
|
||||
quint32 element;
|
||||
quint32 index;
|
||||
};
|
||||
|
||||
static const QByteArray createAngleBinary(
|
||||
const QVector<Attribute> &attributes,
|
||||
const QVector<Sampler> &textureSamplers,
|
||||
const QVector<Sampler> &vertexSamplers,
|
||||
const QVector<Uniform> &uniforms,
|
||||
const QVector<UniformIndex> &uniformIndex,
|
||||
const QByteArray &pixelShader,
|
||||
const QByteArray &vertexShader,
|
||||
const QByteArray &geometryShader = QByteArray(),
|
||||
bool usesPointSize = false)
|
||||
{
|
||||
QByteArray binary;
|
||||
|
||||
QDataStream stream(&binary, QIODevice::WriteOnly);
|
||||
stream.setByteOrder(QDataStream::LittleEndian);
|
||||
|
||||
stream << quint32(GL_PROGRAM_BINARY_ANGLE)
|
||||
<< qint32(AngleMajorVersion)
|
||||
<< qint32(AngleMinorVersion);
|
||||
|
||||
// Vertex attributes
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (i < attributes.size())
|
||||
stream << quint32(attributes[i].type) << attributes[i].name << attributes[i].index;
|
||||
else
|
||||
stream << quint32(GL_NONE) << ShaderString() << qint32(-1);
|
||||
}
|
||||
|
||||
// Texture units
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (i < textureSamplers.size())
|
||||
stream << textureSamplers[i].active << textureSamplers[i].unit << qint32(textureSamplers[i].type);
|
||||
else
|
||||
stream << false << qint32(0) << qint32(Sampler::Texture2D);
|
||||
}
|
||||
|
||||
// Vertex texture units
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (i < vertexSamplers.size())
|
||||
stream << vertexSamplers[i].active << vertexSamplers[i].unit << qint32(vertexSamplers[i].type);
|
||||
else
|
||||
stream << false << qint32(0) << qint32(Sampler::Texture2D);
|
||||
}
|
||||
|
||||
stream << vertexSamplers.size()
|
||||
<< textureSamplers.size()
|
||||
<< usesPointSize;
|
||||
|
||||
stream << size_t(uniforms.size());
|
||||
foreach (const Uniform &uniform, uniforms) {
|
||||
stream << uniform.type << uniform.precision << uniform.name << uniform.arraySize
|
||||
<< uniform.psRegisterIndex << uniform.vsRegisterIndex << uniform.registerCount;
|
||||
}
|
||||
|
||||
stream << size_t(uniformIndex.size());
|
||||
foreach (const UniformIndex &index, uniformIndex)
|
||||
stream << index.name << index.element << index.index;
|
||||
|
||||
stream << quint32(pixelShader.size())
|
||||
<< quint32(vertexShader.size())
|
||||
<< quint32(geometryShader.size());
|
||||
|
||||
stream.writeRawData(pixelShader.constData(), pixelShader.size());
|
||||
stream.writeRawData(vertexShader.constData(), vertexShader.size());
|
||||
if (!geometryShader.isEmpty())
|
||||
stream.writeRawData(geometryShader.constData(), geometryShader.size());
|
||||
|
||||
return binary;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GLES3/gl3ext.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static const GLfloat normCoords[] = { -1, 1, 1, 1, 1, -1, -1, -1 };
|
||||
static const GLfloat quadCoords[] = { 0, 0, 1, 0, 1, 1, 0, 1 };
|
||||
class QWinRTBackingStorePrivate
|
||||
{
|
||||
public:
|
||||
bool initialized;
|
||||
QSize size;
|
||||
QScopedPointer<QOpenGLContext> context;
|
||||
QScopedPointer<QOpenGLFramebufferObject> fbo;
|
||||
QWinRTScreen *screen;
|
||||
QImage paintDevice;
|
||||
};
|
||||
|
||||
QWinRTBackingStore::QWinRTBackingStore(QWindow *window)
|
||||
: QPlatformBackingStore(window)
|
||||
, m_context(new QOpenGLContext)
|
||||
, m_shaderProgram(0)
|
||||
, m_fbo(0)
|
||||
, m_texture(0)
|
||||
, m_screen(static_cast<QWinRTScreen*>(window->screen()->handle()))
|
||||
, m_initialized(false)
|
||||
: QPlatformBackingStore(window), d_ptr(new QWinRTBackingStorePrivate)
|
||||
{
|
||||
Q_D(QWinRTBackingStore);
|
||||
|
||||
d->initialized = false;
|
||||
d->screen = static_cast<QWinRTScreen*>(window->screen()->handle());
|
||||
|
||||
window->setSurfaceType(QSurface::OpenGLSurface); // Required for flipping, but could be done in the swap
|
||||
}
|
||||
|
||||
bool QWinRTBackingStore::initialize()
|
||||
{
|
||||
if (m_initialized)
|
||||
Q_D(QWinRTBackingStore);
|
||||
|
||||
if (d->initialized)
|
||||
return true;
|
||||
|
||||
m_context->setFormat(window()->requestedFormat());
|
||||
m_context->setScreen(window()->screen());
|
||||
if (!m_context->create())
|
||||
d->context.reset(new QOpenGLContext);
|
||||
QSurfaceFormat format = window()->requestedFormat();
|
||||
format.setVersion(3, 0); // Required for ES3 framebuffer blit
|
||||
d->context->setFormat(format);
|
||||
d->context->setScreen(window()->screen());
|
||||
if (!d->context->create())
|
||||
return false;
|
||||
|
||||
if (!m_context->makeCurrent(window()))
|
||||
if (!d->context->makeCurrent(window()))
|
||||
return false;
|
||||
|
||||
glGenFramebuffers(1, &m_fbo);
|
||||
glGenRenderbuffers(1, &m_rbo);
|
||||
glGenTextures(1, &m_texture);
|
||||
m_shaderProgram = glCreateProgram();
|
||||
|
||||
#if 0 // Standard GLES passthrough shader program
|
||||
static const char *vertexShaderSource =
|
||||
"attribute vec4 pos0;\n"
|
||||
"attribute vec2 tex0;\n"
|
||||
"varying vec2 coord;\n"
|
||||
"void main() {\n"
|
||||
" coord = tex0;\n"
|
||||
" gl_Position = pos0;\n"
|
||||
"}\n";
|
||||
static const char *fragmentShaderSource =
|
||||
"uniform sampler2D texture;\n"
|
||||
"varying highp vec2 coord;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = texture2D(texture, coord);\n"
|
||||
"}\n";
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
|
||||
glCompileShader(vertexShader);
|
||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
|
||||
glCompileShader(fragmentShader);
|
||||
glAttachShader(m_shaderProgram, vertexShader);
|
||||
glAttachShader(m_shaderProgram, fragmentShader);
|
||||
glLinkProgram(m_shaderProgram);
|
||||
#else // Precompiled passthrough shader
|
||||
QVector<Attribute> attributes = QVector<Attribute>() << Attribute(GL_FLOAT_VEC4, "pos0", 0)
|
||||
<< Attribute(GL_FLOAT_VEC2, "tex0", 1);
|
||||
QVector<Sampler> textureSamplers = QVector<Sampler>() << Sampler(true, 0, Sampler::Texture2D);
|
||||
QVector<Sampler> vertexSamplers;
|
||||
QVector<Uniform> uniforms = QVector<Uniform>() << Uniform(GL_SAMPLER_2D, 0, "texture", 0, 0, -1, 1);
|
||||
QVector<UniformIndex> uniformsIndex = QVector<UniformIndex>() << UniformIndex("texture", 0, 0);
|
||||
QByteArray pixelShader(reinterpret_cast<const char *>(q_blitps), sizeof(q_blitps));
|
||||
QByteArray vertexShader(reinterpret_cast<const char *>(q_blitvs), sizeof(q_blitvs));
|
||||
QByteArray binary = createAngleBinary(attributes, textureSamplers, vertexSamplers,
|
||||
uniforms, uniformsIndex, pixelShader, vertexShader);
|
||||
glProgramBinaryOES(m_shaderProgram, GL_PROGRAM_BINARY_ANGLE, binary.constData(), binary.size());
|
||||
#endif
|
||||
m_context->doneCurrent();
|
||||
m_initialized = true;
|
||||
d->context->doneCurrent();
|
||||
d->initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
QWinRTBackingStore::~QWinRTBackingStore()
|
||||
{
|
||||
if (!m_initialized)
|
||||
return;
|
||||
glDeleteBuffers(1, &m_fbo);
|
||||
glDeleteRenderbuffers(1, &m_rbo);
|
||||
glDeleteTextures(1, &m_texture);
|
||||
glDeleteProgram(m_shaderProgram);
|
||||
}
|
||||
|
||||
QPaintDevice *QWinRTBackingStore::paintDevice()
|
||||
{
|
||||
return &m_paintDevice;
|
||||
Q_D(QWinRTBackingStore);
|
||||
return &d->paintDevice;
|
||||
}
|
||||
|
||||
void QWinRTBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
{
|
||||
Q_D(QWinRTBackingStore);
|
||||
Q_UNUSED(offset)
|
||||
if (m_size.isEmpty())
|
||||
|
||||
if (d->size.isEmpty())
|
||||
return;
|
||||
|
||||
m_context->makeCurrent(window);
|
||||
const bool ok = d->context->makeCurrent(window);
|
||||
if (!ok)
|
||||
qWarning("unable to flush");
|
||||
|
||||
// Blitting the entire image width trades zero image copy/relayout for a larger texture upload.
|
||||
// Since we're blitting the whole width anyway, the boundingRect() is used in the assumption that
|
||||
// we don't repeat upload. This is of course dependent on the distance between update regions.
|
||||
// Ideally, we would use the GL_EXT_unpack_subimage extension, which should be possible to implement
|
||||
// since D3D11_MAPPED_SUBRESOURCE supports RowPitch (see below).
|
||||
// Note that single-line blits in a loop are *very* slow, so reducing calls to glTexSubImage2D
|
||||
// is probably a good idea anyway.
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||
QRect bounds = region.boundingRect();
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.y(), m_size.width(), bounds.height(),
|
||||
GL_BGRA_EXT, GL_UNSIGNED_BYTE, m_paintDevice.constScanLine(bounds.y()));
|
||||
// TODO: Implement GL_EXT_unpack_subimage in ANGLE for more minimal uploads
|
||||
//glPixelStorei(GL_UNPACK_ROW_LENGTH, image->bytesPerLine());
|
||||
//glTexSubImage2D(GL_TEXTURE_2D, 0, bounds.x(), bounds.y(), bounds.width(), bounds.height(),
|
||||
// GL_BGRA_EXT, GL_UNSIGNED_BYTE, image->scanLine(bounds.y()) + bounds.x() * 4);
|
||||
|
||||
// Bind render buffer
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
|
||||
|
||||
// Bind position
|
||||
glUseProgram(m_shaderProgram);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, normCoords);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, quadCoords);
|
||||
|
||||
// Render
|
||||
const QSize blitSize = m_size * window->devicePixelRatio();
|
||||
glViewport(0, 0, blitSize.width(), blitSize.height());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
// Unbind
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
glUseProgram(0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
const QRect bounds = region.boundingRect();
|
||||
glBindTexture(GL_TEXTURE_2D, d->fbo->texture());
|
||||
// TODO: when ANGLE GLES3 support is finished, use the glPixelStorei functions to minimize upload
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, bounds.y(), d->size.width(), bounds.height(),
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, d->paintDevice.constScanLine(bounds.y()));
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// fast blit - TODO: perform the blit inside swap buffers instead
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_fbo);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, 0);
|
||||
glBlitFramebufferANGLE(0, 0, blitSize.width(), blitSize.height(), // TODO: blit only the changed rectangle
|
||||
0, 0, blitSize.width(), blitSize.height(),
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, d->fbo->handle());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
const int y1 = bounds.height() + bounds.y();
|
||||
const int y2 = d->size.height() - y1;
|
||||
const int x1 = bounds.x();
|
||||
const int x2 = x1 + bounds.width();
|
||||
glBlitFramebuffer(x1, y2, x2, y1,
|
||||
x1, y1, x2, y2,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
m_context->swapBuffers(window);
|
||||
m_context->doneCurrent();
|
||||
d->context->swapBuffers(window);
|
||||
d->context->doneCurrent();
|
||||
}
|
||||
|
||||
void QWinRTBackingStore::resize(const QSize &size, const QRegion &staticContents)
|
||||
{
|
||||
Q_D(QWinRTBackingStore);
|
||||
Q_UNUSED(staticContents)
|
||||
|
||||
if (!initialize())
|
||||
return;
|
||||
|
||||
if (m_size == size)
|
||||
if (d->size == size)
|
||||
return;
|
||||
|
||||
m_size = size;
|
||||
if (m_size.isEmpty())
|
||||
d->size = size;
|
||||
if (d->size.isEmpty())
|
||||
return;
|
||||
|
||||
m_paintDevice = QImage(m_size, QImage::Format_ARGB32_Premultiplied);
|
||||
d->paintDevice = QImage(d->size, QImage::Format_RGBA8888_Premultiplied);
|
||||
|
||||
m_context->makeCurrent(window());
|
||||
// Input texture
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, m_size.width(), m_size.height(),
|
||||
0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
// Render buffer
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_rbo);
|
||||
const QSize blitSize = m_size * window()->devicePixelRatio();
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_BGRA8_EXT, blitSize.width(), blitSize.height());
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
m_context->doneCurrent();
|
||||
const bool ok = d->context->makeCurrent(window());
|
||||
if (!ok)
|
||||
qWarning("unable to resize");
|
||||
|
||||
d->fbo.reset(new QOpenGLFramebufferObject(d->size));
|
||||
|
||||
d->context->doneCurrent();
|
||||
}
|
||||
|
||||
QImage QWinRTBackingStore::toImage() const
|
||||
{
|
||||
Q_D(const QWinRTBackingStore);
|
||||
return d->paintDevice;
|
||||
}
|
||||
|
||||
void QWinRTBackingStore::beginPaint(const QRegion ®ion)
|
||||
{
|
||||
Q_UNUSED(region)
|
||||
resize(window()->size(), QRegion());
|
||||
resize(window()->size(), region);
|
||||
}
|
||||
|
||||
void QWinRTBackingStore::endPaint()
|
||||
|
@ -48,8 +48,8 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QWinRTScreen;
|
||||
class QOpenGLContext;
|
||||
|
||||
class QWinRTBackingStorePrivate;
|
||||
class QWinRTBackingStore : public QPlatformBackingStore
|
||||
{
|
||||
public:
|
||||
@ -60,19 +60,13 @@ public:
|
||||
void endPaint();
|
||||
void flush(QWindow *window, const QRegion ®ion, const QPoint &offset);
|
||||
void resize(const QSize &size, const QRegion &staticContents);
|
||||
QImage toImage() const Q_DECL_OVERRIDE { return m_paintDevice; }
|
||||
QImage toImage() const Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
bool initialize();
|
||||
bool m_initialized;
|
||||
QSize m_size;
|
||||
QScopedPointer<QOpenGLContext> m_context;
|
||||
quint32 m_shaderProgram;
|
||||
quint32 m_fbo;
|
||||
quint32 m_rbo;
|
||||
quint32 m_texture;
|
||||
QWinRTScreen *m_screen;
|
||||
QImage m_paintDevice;
|
||||
|
||||
QScopedPointer<QWinRTBackingStorePrivate> d_ptr;
|
||||
Q_DECLARE_PRIVATE(QWinRTBackingStore)
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -56,26 +56,9 @@ HEADERS = \
|
||||
qwinrttheme.h \
|
||||
qwinrtwindow.h
|
||||
|
||||
|
||||
BLIT_INPUT = $$PWD/blit.hlsl
|
||||
fxc_blitps.commands = fxc.exe /nologo /T ps_4_0_level_9_1 /E blitps /Vn q_blitps /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
|
||||
fxc_blitps.output = $$OUT_PWD/blitps.h
|
||||
fxc_blitps.input = BLIT_INPUT
|
||||
fxc_blitps.dependency_type = TYPE_C
|
||||
fxc_blitps.variable_out = HEADERS
|
||||
fxc_blitps.CONFIG += target_predeps
|
||||
fxc_blitvs.commands = fxc.exe /nologo /T vs_4_0_level_9_1 /E blitvs /Vn q_blitvs /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
|
||||
fxc_blitvs.output = $$OUT_PWD/blitvs.h
|
||||
fxc_blitvs.input = BLIT_INPUT
|
||||
fxc_blitvs.dependency_type = TYPE_C
|
||||
fxc_blitvs.variable_out = HEADERS
|
||||
fxc_blitvs.CONFIG += target_predeps
|
||||
QMAKE_EXTRA_COMPILERS += fxc_blitps fxc_blitvs
|
||||
|
||||
winphone:equals(WINSDK_VER, 8.0): {
|
||||
SOURCES -= qwinrtplatformmessagedialoghelper.cpp
|
||||
HEADERS -= qwinrtplatformmessagedialoghelper.h
|
||||
}
|
||||
|
||||
OTHER_FILES += winrt.json \
|
||||
blit.hlsl
|
||||
OTHER_FILES += winrt.json
|
||||
|
Loading…
Reference in New Issue
Block a user