An error occurred while loading the file. Please try again.
-
Pasi Keranen authored
Change-Id: I460bc51d308e3743151e2fec6bfea2d197ff18d3 Reviewed-by:
Pasi Keränen <pasi.keranen@digia.com>
381af6de
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCanvas3D module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL3$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPLv3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or later as published by the Free
** Software Foundation and appearing in the file LICENSE.GPL included in
** the packaging of this file. Please review the following information to
** ensure the GNU General Public License version 2.0 requirements will be
** met: http://www.gnu.org/licenses/gpl-2.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "canvasglstatedump_p.h"
#include "activeinfo3d_p.h"
#include "canvas3d_p.h"
#include "context3d_p.h"
#include "texture3d_p.h"
#include "shader3d_p.h"
#include "program3d_p.h"
#include "buffer3d_p.h"
#include "framebuffer3d_p.h"
#include "renderbuffer3d_p.h"
#include "uniformlocation_p.h"
#include "teximage3d_p.h"
#include "arrayutils_p.h"
#include "shaderprecisionformat_p.h"
#include "enumtostringmap_p.h"
#include "canvas3dcommon_p.h"
#include <QtGui/QOpenGLShader>
#include <QtQml/private/qv4typedarray_p.h>
#include <QtQml/private/qv4arraybuffer_p.h>
#include <QtQml/private/qjsvalue_p.h>
#include <QtCore/private/qbytedata_p.h>
QT_BEGIN_NAMESPACE
QT_CANVAS3D_BEGIN_NAMESPACE
/*!
* \qmltype Context3D
* \since QtCanvas3D 1.0
* \ingroup qtcanvas3d-qml-types
* \brief Provides the 3D rendering API and context.
*
* An uncreatable QML type that provides a WebGL-like API that can be used to draw 3D graphics to
* the Canvas3D element. You can get it by calling \l{Canvas3D::getContext}{Canvas3D.getContext}
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
* method.
*
* \sa Canvas3D
*/
CanvasContext::CanvasContext(QOpenGLContext *context, QSurface *surface, QQmlEngine *engine,
int width, int height, bool isES2, QObject *parent) :
CanvasAbstractObject(parent),
QOpenGLFunctions(context),
m_engine(engine),
m_v4engine(QQmlEnginePrivate::getV4Engine(engine)),
m_unpackFlipYEnabled(false),
m_unpackPremultiplyAlphaEnabled(false),
m_glViewportRect(0, 0, width, height),
m_devicePixelRatio(1.0),
m_currentProgram(0),
m_currentArrayBuffer(0),
m_currentElementArrayBuffer(0),
m_currentTexture2D(0),
m_context(context),
m_surface(surface),
m_error(NO_ERROR),
m_currentFramebuffer(0),
m_map(EnumToStringMap::newInstance()),
m_canvas(0),
m_maxVertexAttribs(0),
m_isOpenGLES2(isES2),
m_stateDumpExt(0),
m_standardDerivatives(0)
{
m_extensions = m_context->extensions();
int value = 0;
glGetIntegerv(MAX_VERTEX_ATTRIBS, &value);
m_maxVertexAttribs = uint(value);
#ifndef QT_NO_DEBUG
const GLubyte *version = glGetString(GL_VERSION);
qCDebug(canvas3dinfo).nospace() << "Context3D::" << __FUNCTION__
<< "OpenGL version:" << (const char *)version;
version = glGetString(GL_SHADING_LANGUAGE_VERSION);
qCDebug(canvas3dinfo).nospace() << "Context3D::" << __FUNCTION__
<< "GLSL version:" << (const char *)version;
qCDebug(canvas3dinfo).nospace() << "Context3D::" << __FUNCTION__
<< "EXTENSIONS: " << m_extensions;
#endif
}
/*!
* \internal
*/
CanvasContext::~CanvasContext()
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__;
EnumToStringMap::deleteInstance();
}
/*!
* \internal
*/
void CanvasContext::setCanvas(Canvas *canvas)
{
if (m_canvas != canvas) {
if (m_canvas) {
disconnect(m_canvas, &QQuickItem::widthChanged, this, 0);
disconnect(m_canvas, &QQuickItem::heightChanged, this, 0);
}
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
m_canvas = canvas;
emit canvasChanged(canvas);
connect(m_canvas, &QQuickItem::widthChanged,
this, &CanvasContext::drawingBufferWidthChanged);
connect(m_canvas, &QQuickItem::heightChanged,
this, &CanvasContext::drawingBufferHeightChanged);
}
}
/*!
* \qmlproperty Canvas3D Context3D::canvas
* Holds the read only reference to the Canvas3D for this Context3D.
*/
Canvas *CanvasContext::canvas()
{
return m_canvas;
}
/*!
* \qmlproperty int Context3D::drawingBufferWidth
* Holds the current read-only logical pixel width of the drawing buffer. To get width in physical pixels
* you need to multiply this with the \c devicePixelRatio.
*/
uint CanvasContext::drawingBufferWidth()
{
uint width = 0;
if (m_canvas)
width = m_canvas->width();
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(): " << width;
return width;
}
/*!
* \qmlproperty int Context3D::drawingBufferHeight
* Holds the current read-only logical pixel height of the drawing buffer. To get height in physical pixels
* you need to multiply this with the \c devicePixelRatio.
*/
uint CanvasContext::drawingBufferHeight()
{
uint height = 0;
if (m_canvas)
height = m_canvas->height();
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(): " << height;
return height;
}
/*!
* \internal
*/
QString CanvasContext::glEnumToString(glEnums value) const
{
return m_map->lookUp(value);
}
/*!
* \internal
*/
void CanvasContext::logAllGLErrors(const QString &funcName)
{
if (!((QLoggingCategory &) canvas3dglerrors()).isDebugEnabled())
return;
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
qCWarning(canvas3dglerrors).nospace() << "Context3D::" << funcName
<< ": OpenGL ERROR: "
<< glEnumToString(CanvasContext::glEnums(err));
}
}
/*!
* \internal
*/
void CanvasContext::setContextAttributes(const CanvasContextAttributes &attribs)
{
m_contextAttributes.setFrom(attribs);
}
/*!
* \internal
*/
float CanvasContext::devicePixelRatio()
{
return m_devicePixelRatio;
}
/*!
* \internal
*/
void CanvasContext::setDevicePixelRatio(float ratio)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ << "(" << ratio << ")";
m_devicePixelRatio = ratio;
}
/*!
* \internal
*/
QRect CanvasContext::glViewportRect() const
{
return m_glViewportRect;
}
/*!
* \internal
*/
GLuint CanvasContext::currentFramebuffer()
{
if (!m_currentFramebuffer)
return 0;
return m_currentFramebuffer->id();
}
/*!
* \qmlmethod ShaderPrecisionFormat Context3D::getShaderPrecisionFormat(glEnums shadertype, glEnums precisiontype)
* Return a new ShaderPrecisionFormat describing the range and precision for the specified shader
* numeric format.
* \a shadertype Type of the shader, either \c Context3D.FRAGMENT_SHADER or
* \c{Context3D.VERTEX_SHADER}.
* \a precisiontype Can be \c{Context3D.LOW_FLOAT}, \c{Context3D.MEDIUM_FLOAT},
* \c{Context3D.HIGH_FLOAT}, \c{Context3D.LOW_INT}, \c{Context3D.MEDIUM_INT} or
* \c{Context3D.HIGH_INT}.
*
* \sa ShaderPrecisionFormat
*/
/*!
* \internal
*/
QJSValue CanvasContext::getShaderPrecisionFormat(glEnums shadertype,
glEnums precisiontype)
{
QString str = QString(__FUNCTION__);
str += QStringLiteral("(shaderType:")
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
+ glEnumToString(shadertype)
+ QStringLiteral(", precisionType:")
+ glEnumToString(precisiontype)
+ QStringLiteral(")");
qCDebug(canvas3drendering).nospace() << "Context3D::" << str;
GLint range[2];
range[0] = 1;
range[1] = 1;
GLint precision = 1;
glGetShaderPrecisionFormat((GLenum)(shadertype), (GLenum)(precisiontype), range, &precision);
logAllGLErrors(str);
CanvasShaderPrecisionFormat *format = new CanvasShaderPrecisionFormat();
format->setPrecision(int(precision));
format->setRangeMin(int(range[0]));
format->setRangeMax(int(range[1]));
return m_engine->newQObject(format);
}
/*!
* \qmlmethod bool Context3D::isContextLost()
* Always returns false.
*/
/*!
* \internal
*/
bool CanvasContext::isContextLost()
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(): false";
return false;
}
/*!
* \qmlmethod ContextAttributes Context3D::getContextAttributes()
* Returns a copy of the actual context parameters that are used in the current context.
*/
/*!
* \internal
*/
QJSValue CanvasContext::getContextAttributes()
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ << "()";
CanvasContextAttributes *attributes = new CanvasContextAttributes();
attributes->setAlpha(m_contextAttributes.alpha());
attributes->setDepth(m_contextAttributes.depth());
attributes->setStencil(m_contextAttributes.stencil());
attributes->setAntialias(m_contextAttributes.antialias());
attributes->setPremultipliedAlpha(m_contextAttributes.premultipliedAlpha());
attributes->setPreserveDrawingBuffer(m_contextAttributes.preserveDrawingBuffer());
attributes->setPreferLowPowerToHighPerformance(
m_contextAttributes.preferLowPowerToHighPerformance());
attributes->setFailIfMajorPerformanceCaveat(
m_contextAttributes.failIfMajorPerformanceCaveat());
return m_engine->newQObject(attributes);
}
/*!
* \qmlmethod void Context3D::flush()
* Indicates to graphics driver that previously sent commands must complete within finite time.
*/
/*!
* \internal
*/
void CanvasContext::flush()
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "()";
glFlush();
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::finish()
* Forces all previous 3D rendering commands to complete.
*/
/*!
* \internal
*/
void CanvasContext::finish()
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "()";
glFinish();
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod Texture3D Context3D::createTexture()
* Create a Texture3D object and initialize a name for it as by calling \c{glGenTextures()}.
*/
/*!
* \internal
*/
QJSValue CanvasContext::createTexture()
{
CanvasTexture *texture = new CanvasTexture(this);
QJSValue value = m_engine->newQObject(texture);
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "():" << value.toString();
logAllGLErrors(__FUNCTION__);
return value;
}
/*!
* \qmlmethod void Context3D::deleteTexture(Texture3D texture3D)
* Deletes the given texture as if by calling \c{glDeleteTextures()}.
* Calling this method repeatedly on the same object has no side effects.
* \a texture3D is the Texture3D to be deleted.
*/
/*!
* \internal
*/
void CanvasContext::deleteTexture(QJSValue texture3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(texture:" << texture3D.toString()
<< ")";
CanvasTexture *texture = getAsTexture3D(texture3D);
if (!texture) {
texture->del();
logAllGLErrors(__FUNCTION__);
} else {
m_error = INVALID_VALUE;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID texture handle:" << texture3D.toString();
}
}
/*!
* \qmlmethod void Context3D::scissor(int x, int y, int width, int height)
* Defines a rectangle that constrains the drawing.
* \a x is theleft edge of the rectangle.
* \a y is the bottom edge of the rectangle.
* \a width is the width of the rectangle.
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
* \a height is the height of the rectangle.
*/
/*!
* \internal
*/
void CanvasContext::scissor(int x, int y, int width, int height)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(x:" << x
<< ", y:" << y
<< ", width:" << width
<< ", height:" << height
<< ")";
glScissor(x, y, width, height);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::activeTexture(glEnums texture)
* Sets the given texture unit as active. Number of texture units is implementation dependent,
* but must be at least 8. Initially \c Context3D.TEXTURE0 is active.
* \a texture must be one of \c Context3D.TEXTUREi values where \c i ranges from \c 0 to
* \c{(Context3D.MAX_COMBINED_TEXTURE_IMAGE_UNITS-1)}.
*/
/*!
* \internal
*/
void CanvasContext::activeTexture(glEnums texture)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(texture:" << glEnumToString(texture)
<< ")";
glActiveTexture(GLenum(texture));
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::bindTexture(glEnums target, Texture3D texture3D)
* Bind a Texture3D to a texturing target.
* \a target is the target of the active texture unit to which the Texture3D will be bound.
* Must be either \c{Context3D.TEXTURE_2D} or \c{Context3D.TEXTURE_CUBE_MAP}.
* \a texture3D is the Texture3D to be bound.
*/
/*!
* \internal
*/
void CanvasContext::bindTexture(glEnums target, QJSValue texture3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", texture:" << texture3D.toString()
<< ")";
CanvasTexture *texture = getAsTexture3D(texture3D);
if (target == TEXTURE_2D)
m_currentTexture2D = texture;
else if (target == TEXTURE_CUBE_MAP)
m_currentTextureCubeMap = texture;
if (texture) {
if (!texture->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": Trying to bind deleted texture object";
return;
}
if (target == TEXTURE_2D)
m_currentTexture2D->bind(target);
else if (target == TEXTURE_CUBE_MAP)
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
m_currentTextureCubeMap->bind(target);
} else {
glBindTexture(GLenum(target), 0);
}
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::generateMipmap(glEnums target)
* Generates a complete set of mipmaps for a texture object of the currently active texture unit.
* \a target defines the texture target to which the texture object is bound whose mipmaps will be
* generated. Must be either \c{Context3D.TEXTURE_2D} or \c{Context3D.TEXTURE_CUBE_MAP}.
*/
/*!
* \internal
*/
void CanvasContext::generateMipmap(glEnums target)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ")";
if (target == TEXTURE_2D) {
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No current TEXTURE_2D bound";
m_error = INVALID_OPERATION;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION "
<< "Currently bound TEXTURE_2D is deleted";
m_error = INVALID_OPERATION;
} else {
glGenerateMipmap(target);
logAllGLErrors(__FUNCTION__);
}
} else if (target == TEXTURE_CUBE_MAP) {
if (!m_currentTextureCubeMap) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION "
<< "No current TEXTURE_CUBE_MAP bound";
m_error = INVALID_OPERATION;
} else if (!m_currentTextureCubeMap->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION "
<< "Currently bound TEXTURE_CUBE_MAP is deleted";
m_error = INVALID_OPERATION;
} else {
glGenerateMipmap(target);
logAllGLErrors(__FUNCTION__);
}
}
}
/*!
* \qmlmethod bool Context3D::isTexture(Object anyObject)
* Returns true if the given object is a valid Texture3D object.
* \a anyObject is the object that is to be verified as a valid texture.
*/
/*!
* \internal
*/
bool CanvasContext::isTexture(QJSValue anyObject)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(anyObject:" << anyObject.toString()
<< ")";
CanvasTexture *texture = getAsTexture3D(anyObject);
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
if (!texture)
return false;
return glIsTexture(texture->textureId());
}
/*!
* \internal
*/
CanvasTexture *CanvasContext::getAsTexture3D(QJSValue anyObject)
{
if (!anyObject.isQObject())
return 0;
if (!isOfType(anyObject, "QtCanvas3D::CanvasTexture"))
return 0;
CanvasTexture *texture = static_cast<CanvasTexture *>(anyObject.toQObject());
if (!texture->isAlive())
return 0;
return texture;
}
/*!
* \qmlmethod void Context3D::compressedTexImage2D(glEnums target, int level, glEnums internalformat, int width, int height, int border, TypedArray pixels)
* Not supported, \c{Context3D.INVALID_OPERATION} is generated when called.
* \a target, \a level, \a internalformat, \a width, \a height, \a border and \a pixels are ignored.
*/
/*!
* \internal
*/
void CanvasContext::compressedTexImage2D(glEnums target, int level, glEnums internalformat,
int width, int height, int border,
QJSValue pixels)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", level:" << level
<< ", internalformat:" << glEnumToString(internalformat)
<< ", width:" << width
<< ", height:" << height
<< ", border:" << border
<< ", pixels:" << pixels.toString()
<< ")";
if (target == TEXTURE_2D) {
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION "
<< "No current TEXTURE_2D bound";
m_error = INVALID_OPERATION;
return;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION "
<< "Currently bound TEXTURE_2D is deleted";
m_error = INVALID_OPERATION;
return;
}
} else if (target == TEXTURE_CUBE_MAP) {
if (!m_currentTextureCubeMap) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION "
<< "No current TEXTURE_CUBE_MAP bound";
m_error = INVALID_OPERATION;
return;
} else if (!m_currentTextureCubeMap->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
<< ":INVALID_OPERATION "
<< "Currently bound TEXTURE_CUBE_MAP is deleted";
m_error = INVALID_OPERATION;
return;
}
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, pixels));
if (typedArray) {
glCompressedTexImage2D(target,
level,
internalformat,
width, height, border,
typedArray->byteLength(),
(GLvoid *) typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
} else {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_VALUE pixels must be TypedArray";
m_error = INVALID_VALUE;
return;
}
}
/*!
* \qmlmethod void Context3D::compressedTexSubImage2D(glEnums target, int level, int xoffset, int yoffset, int width, int height, glEnums format, TypedArray pixels)
* Not supported, \c{Context3D.INVALID_OPERATION} is generated when called.
* \a target, \a level, \a xoffset, \a yoffset, \a width, \a height, \a format and \a pixels are
* ignored.
*/
/*!
* \internal
*/
void CanvasContext::compressedTexSubImage2D(glEnums target, int level,
int xoffset, int yoffset,
int width, int height,
glEnums format,
QJSValue pixels)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", level:" << level
<< ", xoffset:" << xoffset
<< ", yoffset:" << yoffset
<< ", width:" << width
<< ", height:" << height
<< ", format:" << glEnumToString(format)
<< ", pixels:" << pixels.toString()
<< ")";
if (target == TEXTURE_2D) {
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No current TEXTURE_2D bound";
m_error = INVALID_OPERATION;
return;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION "
<< "Currently bound TEXTURE_2D is deleted";
m_error = INVALID_OPERATION;
return;
}
} else if (target == TEXTURE_CUBE_MAP) {
if (!m_currentTextureCubeMap) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION "
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
<< "No current TEXTURE_CUBE_MAP bound";
m_error = INVALID_OPERATION;
return;
} else if (!m_currentTextureCubeMap->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION "
<< "Currently bound TEXTURE_CUBE_MAP is deleted";
m_error = INVALID_OPERATION;
return;
}
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, pixels));
if (typedArray) {
glCompressedTexSubImage2D(target,
level,
xoffset, yoffset,
width, height,
format,
typedArray->byteLength(),
(GLvoid *) typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
} else {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_VALUE pixels must be TypedArray";
m_error = INVALID_VALUE;
return;
}
}
/*!
* \qmlmethod void Context3D::copyTexImage2D(glEnums target, int level, glEnums internalformat, int x, int y, int width, int height, int border)
* Copies pixels into currently bound 2D texture.
* \a target specifies the target texture of the active texture unit. Must be \c{Context3D.TEXTURE_2D},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_X}, \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_X},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Y}, \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_Y},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Z}, or \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_Z}.
* \a level specifies the level of detail number. Level \c 0 is the base image level. Level \c n is
* the \c{n}th mipmap reduction image.
* \a internalformat specifies the internal format of the texture. Must be \c{Context3D.ALPHA},
* \c{Context3D.LUMINANCE}, \c{Context3D.LUMINANCE_ALPHA}, \c{Context3D.RGB} or \c{Context3D.RGBA}.
* \a x specifies the window coordinate of the left edge of the rectangular region of pixels to be
* copied.
* \a y specifies the window coordinate of the lower edge of the rectangular region of pixels to be
* copied.
* \a width specifies the width of the texture image. All implementations will support 2D texture
* images that are at least 64 texels wide and cube-mapped texture images that are at least 16
* texels wide.
* \a height specifies the height of the texture image. All implementations will support 2D texture
* images that are at least 64 texels high and cube-mapped texture images that are at least 16
* texels high.
* \a border must be \c{0}.
*/
/*!
* \internal
*/
void CanvasContext::copyTexImage2D(glEnums target, int level, glEnums internalformat,
int x, int y, int width, int height,
int border)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", level:" << level
<< ", internalformat:" << glEnumToString(internalformat)
<< ", x:" << x
<< ", y:" << y
<< ", width:" << width
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
<< ", height:" << height
<< ", border:" << border
<< ")";
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No current texture bound";
m_error = INVALID_OPERATION;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION Currently bound texture is deleted";
m_error = INVALID_OPERATION;
} else {
glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
logAllGLErrors(__FUNCTION__);
}
}
/*!
* \qmlmethod void Context3D::copyTexSubImage2D(glEnums target, int level, int xoffset, int yoffset, int x, int y, int width, int height)
* Copies to into a currently bound 2D texture subimage.
* \a target specifies the target texture of the active texture unit. Must be
* \c{Context3D.TEXTURE_2D},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_X}, \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_X},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Y}, \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_Y},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Z}, or \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_Z}.
* \a level specifies the level of detail number. Level \c 0 is the base image level. Level \c n is
* the \c{n}th mipmap reduction image.
* \a xoffset specifies the texel offset in the x direction within the texture array.
* \a yoffset specifies the texel offset in the y direction within the texture array.
* \a x specifies the window coordinate of the left edge of the rectangular region of pixels to be
* copied.
* \a y specifies the window coordinate of the lower edge of the rectangular region of pixels to be
* copied.
* \a width specifies the width of the texture subimage.
* \a height specifies the height of the texture subimage.
*/
/*!
* \internal
*/
void CanvasContext::copyTexSubImage2D(glEnums target, int level,
int xoffset, int yoffset,
int x, int y,
int width, int height)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", level:" << level
<< ", xoffset:" << xoffset
<< ", yoffset:" << yoffset
<< ", x:" << x
<< ", y:" << y
<< ", width:" << width
<< ", height:" << height
<< ")";
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No current texture bound";
m_error = INVALID_OPERATION;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION Currently bound texture is deleted";
m_error = INVALID_OPERATION;
} else {
copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
logAllGLErrors(__FUNCTION__);
}
}
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
/*!
* \qmlmethod void Context3D::texImage2D(glEnums target, int level, glEnums internalformat, int width, int height, int border, glEnums format, glEnums type, TypedArray pixels)
* Specify a 2D texture image.
* \a target specifies the target texture of the active texture unit. Must be one of:
* \c{Context3D.TEXTURE_2D},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_X}, \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_X},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Y}, \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_Y},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Z}, or \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_Z}.
* \a level specifies the level of detail number. Level \c 0 is the base image level. Level \c n is
* the \c{n}th mipmap reduction image.
* \a internalformat specifies the internal format of the texture. Must be \c{Context3D.ALPHA},
* \c{Context3D.LUMINANCE}, \c{Context3D.LUMINANCE_ALPHA}, \c{Context3D.RGB} or \c{Context3D.RGBA}.
* \a width specifies the width of the texture image. All implementations will support 2D texture
* images that are at least 64 texels wide and cube-mapped texture images that are at least 16
* texels wide.
* \a height specifies the height of the texture image. All implementations will support 2D texture
* images that are at least 64 texels high and cube-mapped texture images that are at least 16
* texels high.
* \a border must be \c{0}.
* \a format specifies the format of the texel data given in \a pixels, must match the value
* of \a internalFormat.
* \a type specifies the data type of the data given in \a pixels, must match the TypedArray type
* of \a pixels. Must be \c{Context3D.UNSIGNED_BYTE}, \c{Context3D.UNSIGNED_SHORT_5_6_5},
* \c{Context3D.UNSIGNED_SHORT_4_4_4_4} or \c{Context3D.UNSIGNED_SHORT_5_5_5_1}.
* \a pixels specifies the TypedArray containing the image data. If pixels is \c{null}, a buffer
* of sufficient size initialized to 0 is passed.
*/
/*!
* \internal
*/
void CanvasContext::texImage2D(glEnums target, int level, glEnums internalformat,
int width, int height, int border,
glEnums format, glEnums type,
QJSValue pixels)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", level:" << level
<< ", internalformat:" << glEnumToString(internalformat)
<< ", width:" << width
<< ", height:" << height
<< ", border:" << border
<< ", format:" << glEnumToString(format)
<< ", type:" << glEnumToString(type)
<< ", pixels:" << pixels.toString()
<< ")";
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::"
<< __FUNCTION__
<< ":INVALID_OPERATION No current texture bound";
m_error = INVALID_OPERATION;
return;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION Currently bound texture is deleted";
m_error = INVALID_OPERATION;
return;
}
int bytesPerPixel = 0;
uchar *srcData = 0;
uchar *unpackedData = 0;
bool deleteTempPixels = false;
if (pixels.isNull()) {
deleteTempPixels = true;
int size = getSufficientSize(type, width, height);
srcData = new uchar[size];
memset(srcData, 0, size);
}
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
switch (type) {
case UNSIGNED_BYTE: {
switch (format) {
case ALPHA:
bytesPerPixel = 1;
break;
case RGB:
bytesPerPixel = 3;
break;
case RGBA:
bytesPerPixel = 4;
break;
case LUMINANCE:
bytesPerPixel = 1;
break;
case LUMINANCE_ALPHA:
bytesPerPixel = 2;
break;
default:
break;
}
if (bytesPerPixel == 0) {
m_error = INVALID_ENUM;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM Invalid format supplied "
<< glEnumToString(format);
return;
}
if (!srcData)
srcData = getAsUint8ArrayRawPtr(pixels);
if (!srcData) {
qCWarning(canvas3drendering) << "Context3D::"
<< __FUNCTION__
<< ":INVALID_OPERATION Expected Uint8Array, received "
<< pixels.toString();
m_error = INVALID_OPERATION;
return;
}
unpackedData = unpackPixels(srcData, false, bytesPerPixel, width, height);
glTexImage2D(target, level, internalformat, width, height,
border, format, type, unpackedData);
logAllGLErrors(__FUNCTION__);
}
break;
case UNSIGNED_SHORT_4_4_4_4:
case UNSIGNED_SHORT_5_6_5:
case UNSIGNED_SHORT_5_5_5_1: {
if (!srcData)
srcData = getAsUint16ArrayRawPtr(pixels);
if (!srcData) {
qCWarning(canvas3drendering) << "Context3D::"
<< __FUNCTION__
<< ":INVALID_OPERATION Expected Uint16Array, received "
<< pixels.toString();
m_error = INVALID_OPERATION;
return;
}
unpackedData = unpackPixels(srcData, false, 2, width, height);
glTexImage2D(target, level, internalformat, width, height,
border, format, type, unpackedData);
logAllGLErrors(__FUNCTION__);
}
break;
default:
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
qCWarning(canvas3drendering) << "Context3D::"
<< __FUNCTION__
<< ":INVALID_ENUM Invalid type enum";
m_error = INVALID_ENUM;
break;
}
// Delete temp data
if (unpackedData != srcData)
delete unpackedData;
if (deleteTempPixels)
delete[] srcData;
}
/*!
* \internal
*/
uchar *CanvasContext::getAsUint8ArrayRawPtr(QJSValue jsValue)
{
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, jsValue));
if (!typedArray)
return 0;
if (typedArray->arrayType() != QV4::Heap::TypedArray::UInt8Array)
return 0;
return reinterpret_cast<unsigned char *>(typedArray->arrayData()->data());
}
/*!
* \internal
*/
uchar *CanvasContext::getAsUint16ArrayRawPtr(QJSValue jsValue)
{
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, jsValue));
if (!typedArray)
return 0;
if (typedArray->arrayType() != QV4::Heap::TypedArray::UInt16Array)
return 0;
return reinterpret_cast<unsigned char *>(typedArray->arrayData()->data());
}
/*!
* \qmlmethod void Context3D::texSubImage2D(glEnums target, int level, int xoffset, int yoffset, int width, int height, glEnums format, glEnums type, TypedArray pixels)
* Specify a 2D texture subimage.
* \a target Target texture of the active texture unit. Must be \c{Context3D.TEXTURE_2D},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_X}, \c{Context3D.TEXTURE_CUBE_MAP__NEGATIVE_X},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Y}, \c{Context3D.TEXTURE_CUBE_MAP__NEGATIVE_Y},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Z}, or \c{Context3D.TEXTURE_CUBE_MAP__NEGATIVE_Z}.
* \a level Level of detail number. Level \c 0 is the base image level. Level \c n is the \c{n}th
* mipmap reduction image.
* \a xoffset Specifies a texel offset in the x direction within the texture array.
* \a yoffset Specifies a texel offset in the y direction within the texture array.
* \a width Width of the texture subimage.
* \a height Height of the texture subimage.
* \a format Format of the texel data given in \a pixels, must match the value
* of \a internalFormat.
* \a type Data type of the data given in \a pixels, must match the TypedArray type
* of \a pixels. Must be \c{Context3D.UNSIGNED_BYTE}, \c{Context3D.UNSIGNED_SHORT_5_6_5},
* \c{Context3D.UNSIGNED_SHORT_4_4_4_4} or \c{Context3D.UNSIGNED_SHORT_5_5_5_1}.
* \a pixels TypedArray containing the image data. If pixels is \c null, a buffer of
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
* sufficient size initialized to 0 is passed.
*/
/*!
* \internal
*/
void CanvasContext::texSubImage2D(glEnums target, int level,
int xoffset, int yoffset,
int width, int height,
glEnums format, glEnums type,
QJSValue pixels)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", level:" << level
<< ", xoffset:" << xoffset
<< ", yoffset:" << yoffset
<< ", width:" << width
<< ", height:" << height
<< ", format:" << glEnumToString(format)
<< ", type:" << glEnumToString(type)
<< ", pixels:" << pixels.toString()
<< ")";
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No current texture bound";
m_error = INVALID_OPERATION;
return;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION Currently bound texture is deleted";
m_error = INVALID_OPERATION;
return;
}
if (pixels.isNull()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_VALUE pixels was null";
m_error = INVALID_VALUE;
return;
}
int bytesPerPixel = 0;
uchar *srcData = 0;
uchar *unpackedData = 0;
switch (type) {
case UNSIGNED_BYTE: {
switch (format) {
case ALPHA:
bytesPerPixel = 1;
break;
case RGB:
bytesPerPixel = 3;
break;
case RGBA:
bytesPerPixel = 4;
break;
case LUMINANCE:
bytesPerPixel = 1;
break;
case LUMINANCE_ALPHA:
bytesPerPixel = 2;
break;
default:
break;
}
if (bytesPerPixel == 0) {
m_error = INVALID_ENUM;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
<< ":INVALID_ENUM Invalid format supplied "
<< glEnumToString(format);
return;
}
srcData = getAsUint8ArrayRawPtr(pixels);
if (!srcData) {
qCWarning(canvas3drendering) << "Context3D::"
<< __FUNCTION__
<< ":INVALID_OPERATION Expected Uint8Array, received "
<< pixels.toString();
m_error = INVALID_OPERATION;
return;
}
unpackedData = unpackPixels(srcData, false, bytesPerPixel, width, height);
glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, unpackedData);
logAllGLErrors(__FUNCTION__);
}
break;
case UNSIGNED_SHORT_4_4_4_4:
case UNSIGNED_SHORT_5_6_5:
case UNSIGNED_SHORT_5_5_5_1: {
srcData = getAsUint16ArrayRawPtr(pixels);
if (!srcData) {
qCWarning(canvas3drendering) << "Context3D::"
<< __FUNCTION__
<< ":INVALID_OPERATION Expected Uint16Array, received "
<< pixels.toString();
m_error = INVALID_OPERATION;
return;
}
unpackedData = unpackPixels(srcData, false, 2, width, height);
glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, unpackedData);
logAllGLErrors(__FUNCTION__);
}
break;
default:
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM Invalid type enum";
m_error = INVALID_ENUM;
break;
}
// Delete temp data
if (unpackedData != srcData)
delete unpackedData;
}
/*!
* \internal
*/
uchar* CanvasContext::unpackPixels(uchar *srcData, bool useSrcDataAsDst,
int bytesPerPixel, int width, int height)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(srcData:" << srcData
<< ", useSrcDataAsDst:" << useSrcDataAsDst
<< ", bytesPerPixel:" << bytesPerPixel
<< ", width:" << width
<< ", height:" << height
<< ")";
// Check if no processing is needed
if (!m_unpackFlipYEnabled || srcData == 0 || width == 0 || height == 0 || bytesPerPixel == 0)
return srcData;
uchar *unpackedData = srcData;
int bytesPerRow = width * bytesPerPixel;
if (m_unpackFlipYEnabled) {
1191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
if (useSrcDataAsDst) {
uchar *row = new uchar[width*bytesPerPixel];
for (int y = 0; y < height; y++) {
memcpy(row,
srcData + y * bytesPerRow,
bytesPerRow);
memcpy(srcData + y * bytesPerRow,
srcData + (height - y - 1) * bytesPerRow,
bytesPerRow);
memcpy(srcData + (height - y - 1) * bytesPerRow,
row,
bytesPerRow);
}
} else {
unpackedData = new uchar[height * bytesPerRow];
for (int y = 0; y < height; y++) {
memcpy(unpackedData + (height - y - 1) * bytesPerRow,
srcData + y * bytesPerRow,
bytesPerRow);
}
}
}
return unpackedData;
}
/*!
* \qmlmethod void Context3D::texImage2D(glEnums target, int level, glEnums internalformat, glEnums format, glEnums type, TextureImage texImage)
* Uploads the given TextureImage element to the currently bound Texture3D.
* \a target Target texture of the active texture unit. Must be \c{Context3D.TEXTURE_2D},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_X}, \c{Context3D.TEXTURE_CUBE_MAP__NEGATIVE_X},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Y}, \c{Context3D.TEXTURE_CUBE_MAP__NEGATIVE_Y},
* \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Z}, or \c{Context3D.TEXTURE_CUBE_MAP__NEGATIVE_Z}.
* \a level Level of detail number. Level \c 0 is the base image level. Level \c n is the \c{n}th
* mipmap reduction image.
* \a internalformat Internal format of the texture, conceptually the given image is first
* converted to this format, then uploaded. Must be \c{Context3D.ALPHA}, \c{Context3D.LUMINANCE},
* \c{Context3D.LUMINANCE_ALPHA}, \c{Context3D.RGB} or \c{Context3D.RGBA}.
* \a format Format of the texture, must match the value of \a internalFormat.
* \a type Type of the data, conceptually the given image is first converted to this type, then
* uploaded. Must be \c{Context3D.UNSIGNED_BYTE}, \c{Context3D.UNSIGNED_SHORT_5_6_5},
* \c{Context3D.UNSIGNED_SHORT_4_4_4_4} or \c{Context3D.UNSIGNED_SHORT_5_5_5_1}.
* \a texImage A complete \c{TextureImage} loaded using the \c{TextureImageLoader}.
*/
/*!
* \internal
*/
void CanvasContext::texImage2D(glEnums target, int level, glEnums internalformat,
glEnums format, glEnums type, QJSValue texImage)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", level:" << level
<< ", internalformat:" << glEnumToString(internalformat)
<< ", format:" << glEnumToString(format)
<< ", type:" << glEnumToString(type)
<< ", texImage:" << texImage.toString()
<< ")";
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No current texture bound";
m_error = INVALID_OPERATION;
return;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION Currently bound texture is deleted";
m_error = INVALID_OPERATION;
return;
}
1261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
CanvasTextureImage *image = getAsTextureImage(texImage);
if (!image) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_VALUE invalid texImage "
<< texImage.toString();
m_error = INVALID_VALUE;
return;
}
uchar *pixels = 0;
switch (type) {
case UNSIGNED_BYTE:
pixels = image->convertToFormat(type, m_unpackFlipYEnabled, m_unpackPremultiplyAlphaEnabled);
break;
case UNSIGNED_SHORT_5_6_5:
case UNSIGNED_SHORT_4_4_4_4:
case UNSIGNED_SHORT_5_5_5_1:
pixels = image->convertToFormat(type, m_unpackFlipYEnabled, m_unpackPremultiplyAlphaEnabled);
break;
default:
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM Invalid type enum";
m_error = INVALID_ENUM;
return;
}
if (pixels == 0) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":Conversion of pixels to format failed.";
return;
}
if (!m_currentTexture2D->hasSpecificName()) {
m_currentTexture2D->setName("ImageTexture_"+image->name());
}
glTexImage2D(target, level, internalformat, image->width(), image->height(), 0, format, type,
pixels);
logAllGLErrors(__FUNCTION__);
}
/*!
* \internal
*/
CanvasTextureImage* CanvasContext::getAsTextureImage(QJSValue anyObject)
{
if (!anyObject.isQObject())
return 0;
if (!isOfType(anyObject, "QtCanvas3D::CanvasTextureImage"))
return 0;
CanvasTextureImage *texImage = static_cast<CanvasTextureImage *>(anyObject.toQObject());
return texImage;
}
/*!
* \qmlmethod void Context3D::texSubImage2D(glEnums target, int level, int xoffset, int yoffset, glEnums format, glEnums type, TextureImage texImage)
* Uploads the given TextureImage element to the currently bound Texture3D.
* \a target specifies the target texture of the active texture unit. Must be
* \c{Context3D.TEXTURE_2D}, \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_X},
* \c{Context3D.TEXTURE_CUBE_MAP__NEGATIVE_X}, \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Y},
* \c{Context3D.TEXTURE_CUBE_MAP__NEGATIVE_Y}, \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Z}, or
* \c{Context3D.TEXTURE_CUBE_MAP__NEGATIVE_Z}.
* \a level Level of detail number. Level \c 0 is the base image level. Level \c n is the \c{n}th
* mipmap reduction image.
* \a internalformat Internal format of the texture, conceptually the given image is first
* converted to this format, then uploaded. Must be \c{Context3D.ALPHA}, \c{Context3D.LUMINANCE},
1331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
* \c{Context3D.LUMINANCE_ALPHA}, \c{Context3D.RGB} or \c{Context3D.RGBA}.
* \a format Format of the texture, must match the value of \a internalFormat.
* \a type Type of the data, conceptually the given image is first converted to this type, then
* uploaded. Must be \c{Context3D.UNSIGNED_BYTE}, \c{Context3D.UNSIGNED_SHORT_5_6_5},
* \c{Context3D.UNSIGNED_SHORT_4_4_4_4} or \c{Context3D.UNSIGNED_SHORT_5_5_5_1}.
* \a texImage A complete \c{TextureImage} loaded using the \c{TextureImageLoader}.
*/
/*!
* \internal
*/
void CanvasContext::texSubImage2D(glEnums target, int level,
int xoffset, int yoffset,
glEnums format, glEnums type, QJSValue texImage)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "( target:" << glEnumToString(target)
<< ", level:" << level
<< ", xoffset:" << xoffset
<< ", yoffset:" << yoffset
<< ", format:" << glEnumToString(format)
<< ", type:" << glEnumToString(type)
<< ", texImage:" << texImage.toString()
<< ")";
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No current texture bound";
m_error = INVALID_OPERATION;
return;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION Currently bound texture is deleted";
m_error = INVALID_OPERATION;
return;
}
CanvasTextureImage *image = getAsTextureImage(texImage);
if (!image) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_VALUE invalid texImage "
<< texImage.toString();
m_error = INVALID_VALUE;
return;
}
uchar *pixels = 0;
switch (type) {
case UNSIGNED_BYTE:
pixels = image->convertToFormat(type,
m_unpackFlipYEnabled,
m_unpackPremultiplyAlphaEnabled);
break;
case UNSIGNED_SHORT_5_6_5:
case UNSIGNED_SHORT_4_4_4_4:
case UNSIGNED_SHORT_5_5_5_1:
pixels = image->convertToFormat(type,
m_unpackFlipYEnabled,
m_unpackPremultiplyAlphaEnabled);
break;
default:
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM Invalid type enum";
m_error = INVALID_ENUM;
return;
}
if (pixels == 0) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":Conversion of pixels to format failed.";
return;
1401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
}
glTexSubImage2D(target, level, xoffset, yoffset, image->width(), image->height(), format,
type, pixels);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::texParameterf(glEnums target, glEnums pname, float param)
* Sets texture parameters.
* \a target specifies the target texture of the active texture unit. Must be
* \c{Context3D.TEXTURE_2D} or \c{Context3D.TEXTURE_CUBE_MAP}.
* \a pname specifies the symbolic name of a texture parameter. pname can be
* \c{Context3D.TEXTURE_MIN_FILTER}, \c{Context3D.TEXTURE_MAG_FILTER}, \c{Context3D.TEXTURE_WRAP_S} or
* \c{Context3D.TEXTURE_WRAP_T}.
* \a param specifies the new float value to be set to \a pname
*/
/*!
* \internal
*/
void CanvasContext::texParameterf(glEnums target, glEnums pname, float param)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "( target:" << glEnumToString(target)
<< ", pname:" << glEnumToString(pname)
<< ", param:" << param
<< ")";
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No current texture bound";
m_error = INVALID_OPERATION;
return;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION Currently bound texture is deleted";
m_error = INVALID_OPERATION;
return;
}
glTexParameterf(GLenum(target), GLenum(pname), GLfloat(param));
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::texParameteri(glEnums target, glEnums pname, float param)
* Sets texture parameters.
* \a target specifies the target texture of the active texture unit. Must be
* \c{Context3D.TEXTURE_2D} or \c{Context3D.TEXTURE_CUBE_MAP}.
* \a pname specifies the symbolic name of a texture parameter. pname can be
* \c{Context3D.TEXTURE_MIN_FILTER}, \c{Context3D.TEXTURE_MAG_FILTER}, \c{Context3D.TEXTURE_WRAP_S} or
* \c{Context3D.TEXTURE_WRAP_T}.
* \a param specifies the new int value to be set to \a pname
*/
/*!
* \internal
*/
void CanvasContext::texParameteri(glEnums target, glEnums pname, int param)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", pname:" << glEnumToString(pname)
<< ", param:" << glEnumToString(glEnums(param))
<< ")";
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No current texture bound";
m_error = INVALID_OPERATION;
return;
} else if (!m_currentTexture2D->isAlive()) {
1471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION Currently bound texture is deleted";
m_error = INVALID_OPERATION;
return;
}
glTexParameteri(GLenum(target), GLenum(pname), GLint(param));
logAllGLErrors(__FUNCTION__);
}
/*!
* \internal
*/
int CanvasContext::getSufficientSize(glEnums internalFormat, int width, int height)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "( internalFormat:" << glEnumToString(internalFormat)
<< " , width:" << width
<< ", height:" << height
<< ")";
int bytesPerPixel = 0;
switch (internalFormat) {
case UNSIGNED_BYTE:
bytesPerPixel = 4;
break;
case UNSIGNED_SHORT_5_6_5:
case UNSIGNED_SHORT_4_4_4_4:
case UNSIGNED_SHORT_5_5_5_1:
bytesPerPixel = 2;
break;
default:
break;
}
return width * height * bytesPerPixel;
}
/*!
* \qmlmethod FrameBuffer3D Context3D::createFramebuffer()
* Returns a created FrameBuffer3D object that is initialized with a framebuffer object name as
* if by calling \c{glGenFramebuffers()}.
*/
/*!
* \internal
*/
QJSValue CanvasContext::createFramebuffer()
{
CanvasFrameBuffer *framebuffer = new CanvasFrameBuffer(this);
QJSValue value = m_engine->newQObject(framebuffer);
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< ":" << value.toString();
logAllGLErrors(__FUNCTION__);
return value;
}
/*!
* \qmlmethod void Context3D::bindFramebuffer(glEnums target, FrameBuffer3D buffer)
* Binds the given \a buffer object to the given \a target.
* \a target must be \c{Context3D.FRAMEBUFFER}.
*/
/*!
* \internal
*/
void CanvasContext::bindFramebuffer(glEnums target, QJSValue buffer)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", framebuffer:" << buffer.toString() << ")";
1541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610
if (target != FRAMEBUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): INVALID_ENUM bind target, must be FRAMEBUFFER";
m_error = INVALID_ENUM;
return;
}
CanvasFrameBuffer *framebuffer = getAsFramebuffer(buffer);
if (framebuffer)
m_currentFramebuffer = framebuffer;
else
m_currentFramebuffer = 0;
// Let canvas component figure out the exact frame buffer id to use
m_canvas->bindCurrentRenderTarget();
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod Context3D::glEnums Context3D::checkFramebufferStatus(glEnums target)
* Returns the completeness status of the framebuffer object.
* \a target must be \c{Context3D.FRAMEBUFFER}.
*
*/
/*!
* \internal
*/
CanvasContext::glEnums CanvasContext::checkFramebufferStatus(glEnums target)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ")";
if (target != FRAMEBUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_ENUM bind target, must be FRAMEBUFFER";
m_error = INVALID_ENUM;
return FRAMEBUFFER_UNSUPPORTED;
}
if (m_currentFramebuffer) {
return glEnums(glCheckFramebufferStatus(GL_FRAMEBUFFER));
} else {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_OPERATION no current framebuffer bound";
m_error = INVALID_OPERATION;
return FRAMEBUFFER_UNSUPPORTED;
}
}
/*!
* \qmlmethod void Context3D::framebufferRenderbuffer(glEnums target, glEnums attachment, glEnums renderbuffertarget, RenderBuffer3D renderbuffer3D)
* Attaches the given \a renderbuffer3D object to the \a attachment point of the current framebuffer
* object.
* \a target must be \c{Context3D.FRAMEBUFFER}. \a renderbuffertarget must
* be \c{Context3D.RENDERBUFFER}.
*/
/*!
* \internal
*/
void CanvasContext::framebufferRenderbuffer(glEnums target, glEnums attachment,
glEnums renderbuffertarget,
QJSValue renderbuffer3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< "attachment:" << glEnumToString(attachment)
<< "renderbuffertarget:" << glEnumToString(renderbuffertarget)
<< ", renderbuffer3D:" << renderbuffer3D.toString()
<< ")";
1611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
if (target != FRAMEBUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_ENUM bind target, must be FRAMEBUFFER";
m_error = INVALID_ENUM;
return;
}
if (!m_currentFramebuffer) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): INVALID_OPERATION no framebuffer bound";
m_error = INVALID_OPERATION;
return;
}
if (attachment != COLOR_ATTACHMENT0
&& attachment != DEPTH_ATTACHMENT
&& attachment != STENCIL_ATTACHMENT
&& attachment != DEPTH_STENCIL_ATTACHMENT) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): INVALID_OPERATION attachment must be one of "
<< "COLOR_ATTACHMENT0, DEPTH_ATTACHMENT, STENCIL_ATTACHMENT "
<< "or DEPTH_STENCIL_ATTACHMENT";
m_error = INVALID_OPERATION;
return;
}
CanvasRenderBuffer *renderbuffer = getAsRenderbuffer3D(renderbuffer3D);
if (renderbuffer && renderbuffertarget != RENDERBUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): INVALID_OPERATION renderbuffertarget must be "
<< "RENDERBUFFER for non null renderbuffers";
m_error = INVALID_OPERATION;
return;
}
GLuint renderbufferId = renderbuffer ? renderbuffer->id() : 0;
glFramebufferRenderbuffer(GLenum(target),
GLenum(attachment),
GLenum(renderbuffertarget),
renderbufferId);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::framebufferTexture2D(glEnums target, glEnums attachment, glEnums textarget, Texture3D texture3D, int level)
* Attaches the given \a renderbuffer object to the \a attachment point of the current framebuffer
* object.
* \a target must be \c{Context3D.FRAMEBUFFER}. \a renderbuffertarget must
* be \c{Context3D.RENDERBUFFER}.
*/
/*!
* \internal
*/
void CanvasContext::framebufferTexture2D(glEnums target, glEnums attachment, glEnums textarget,
QJSValue texture3D, int level)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", attachment:" << glEnumToString(attachment)
<< ", textarget:" << glEnumToString(textarget)
<< ", texture:" << texture3D.toString()
<< ", level:" << level
<< ")";
if (target != FRAMEBUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): INVALID_ENUM bind target, must be FRAMEBUFFER";
m_error = INVALID_ENUM;
return;
1681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750
}
if (!m_currentFramebuffer) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): INVALID_OPERATION no current framebuffer bound";
m_error = INVALID_OPERATION;
return;
}
if (attachment != COLOR_ATTACHMENT0 && attachment != DEPTH_ATTACHMENT
&& attachment != STENCIL_ATTACHMENT) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): INVALID_OPERATION attachment must be one of "
<< "COLOR_ATTACHMENT0, DEPTH_ATTACHMENT or STENCIL_ATTACHMENT";
m_error = INVALID_OPERATION;
return;
}
CanvasTexture *texture = getAsTexture3D(texture3D);
if (texture) {
if (textarget != TEXTURE_2D
&& textarget != TEXTURE_CUBE_MAP_POSITIVE_X
&& textarget != TEXTURE_CUBE_MAP_POSITIVE_Y
&& textarget != TEXTURE_CUBE_MAP_POSITIVE_Z
&& textarget != TEXTURE_CUBE_MAP_NEGATIVE_X
&& textarget != TEXTURE_CUBE_MAP_NEGATIVE_Y
&& textarget != TEXTURE_CUBE_MAP_NEGATIVE_Z) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): textarget must be one of TEXTURE_2D, "
<< "TEXTURE_CUBE_MAP_POSITIVE_X, "
<< "TEXTURE_CUBE_MAP_POSITIVE_Y, "
<< "TEXTURE_CUBE_MAP_POSITIVE_Z, "
<< "TEXTURE_CUBE_MAP_NEGATIVE_X, "
<< "TEXTURE_CUBE_MAP_NEGATIVE_Y or "
<< "TEXTURE_CUBE_MAP_NEGATIVE_Z";
m_error = INVALID_OPERATION;
return;
}
if (level != 0) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): INVALID_VALUE level must be 0";
m_error = INVALID_VALUE;
return;
}
}
GLuint textureId = texture ? texture->textureId() : 0;
glFramebufferTexture2D(GLenum(target), GLenum(attachment), GLenum(textarget), textureId, level);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::isFramebuffer(Object anyObject)
* Returns true if the given object is a valid FrameBuffer3D object.
* \a anyObject is the object that is to be verified as a valid framebuffer.
*/
/*!
* \internal
*/
bool CanvasContext::isFramebuffer(QJSValue anyObject)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "( anyObject:" << anyObject.toString()
<< ")";
CanvasFrameBuffer *fbo = getAsFramebuffer(anyObject);
if (fbo)
return glIsFramebuffer(fbo->id());
1751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820
else
return false;
}
/*!
* \internal
*/
CanvasFrameBuffer *CanvasContext::getAsFramebuffer(QJSValue anyObject)
{
if (!anyObject.isQObject())
return 0;
if (!isOfType(anyObject, "QtCanvas3D::CanvasFrameBuffer"))
return 0;
CanvasFrameBuffer *fbo = static_cast<CanvasFrameBuffer *>(anyObject.toQObject());
if (!fbo->isAlive())
return 0;
return fbo;
}
/*!
* \qmlmethod void Context3D::deleteFramebuffer(FrameBuffer3D buffer)
* Deletes the given framebuffer as if by calling \c{glDeleteFramebuffers()}.
* Calling this method repeatedly on the same object has no side effects.
* \a buffer is the FrameBuffer3D to be deleted.
*/
/*!
* \internal
*/
void CanvasContext::deleteFramebuffer(QJSValue buffer)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "( buffer:" << buffer.toString()
<< ")";
CanvasFrameBuffer *fbo = getAsFramebuffer(buffer);
if (fbo) {
fbo->del();
logAllGLErrors(__FUNCTION__);
} else {
m_error = INVALID_VALUE;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): INVALID_VALUE buffer handle";
}
}
/*!
* \qmlmethod RenderBuffer3D Context3D::createRenderbuffer()
* Returns a created RenderBuffer3D object that is initialized with a renderbuffer object name
* as if by calling \c{glGenRenderbuffers()}.
*/
/*!
* \internal
*/
QJSValue CanvasContext::createRenderbuffer()
{
CanvasRenderBuffer *renderbuffer = new CanvasRenderBuffer(this);
QJSValue value = m_engine->newQObject(renderbuffer);
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "():" << value.toString();
logAllGLErrors(__FUNCTION__);
return value;
}
/*!
* \qmlmethod void Context3D::bindRenderbuffer(glEnums target, RenderBuffer3D renderbuffer)
* Binds the given \a renderbuffer3D object to the given \a target.
1821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890
* \a target must be \c{Context3D.RENDERBUFFER}.
*/
/*!
* \internal
*/
void CanvasContext::bindRenderbuffer(glEnums target, QJSValue renderbuffer3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", renderbuffer3D:" << renderbuffer3D.toString()
<< ")";
if (target != RENDERBUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_ENUM target must be RENDERBUFFER";
m_error = INVALID_ENUM;
return;
}
CanvasRenderBuffer *renderbuffer = getAsRenderbuffer3D(renderbuffer3D);
if (renderbuffer) {
m_currentRenderbuffer = renderbuffer;
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer->id());
} else {
m_currentRenderbuffer = 0;
glBindRenderbuffer(GL_RENDERBUFFER, 0);
}
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::renderbufferStorage(glEnums target, glEnums internalformat, int width, int height)
* Create and initialize a data store for the \c renderbuffer object.
* \a target must be \c Context3D.RENDERBUFFER.
* \a internalformat specifies the color-renderable, depth-renderable or stencil-renderable format
* of the renderbuffer. Must be one of \c{Context3D.RGBA4}, \c{Context3D.RGB565}, \c{Context3D.RGB5_A1},
* \c{Context3D.DEPTH_COMPONENT16} or \c{Context3D.STENCIL_INDEX8}.
* \a width specifies the renderbuffer width in pixels.
* \a height specifies the renderbuffer height in pixels.
*/
/*!
* \internal
*/
void CanvasContext::renderbufferStorage(glEnums target, glEnums internalformat,
int width, int height)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", internalformat:" << glEnumToString(internalformat)
<< ", width:" << width
<< ", height:" << height
<< ")";
if (target != RENDERBUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_ENUM target must be RENDERBUFFER";
m_error = INVALID_ENUM;
return;
}
glRenderbufferStorage(GLenum(target), GLenum(internalformat), width, height);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod bool Context3D::isRenderbuffer(Object anyObject)
* Returns true if the given object is a valid RenderBuffer3D object.
* \a anyObject is the object that is to be verified as a valid renderbuffer.
*/
/*!
1891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960
* \internal
*/
bool CanvasContext::isRenderbuffer(QJSValue anyObject)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(anyObject:" << anyObject.toString()
<< ")";
CanvasRenderBuffer *rbo = getAsRenderbuffer3D(anyObject);
if (!rbo)
return false;
return glIsRenderbuffer(rbo->id());
}
/*!
* \internal
*/
CanvasRenderBuffer *CanvasContext::getAsRenderbuffer3D(QJSValue anyObject) const
{
if (!anyObject.isQObject())
return 0;
if (!isOfType(anyObject, "QtCanvas3D::CanvasRenderBuffer"))
return 0;
CanvasRenderBuffer *rbo = static_cast<CanvasRenderBuffer *>(anyObject.toQObject());
if (!rbo->isAlive())
return 0;
return rbo;
}
/*!
* \qmlmethod void Context3D::deleteRenderbuffer(RenderBuffer3D renderbuffer3D)
* Deletes the given renderbuffer as if by calling \c{glDeleteRenderbuffers()}.
* Calling this method repeatedly on the same object has no side effects.
* \a renderbuffer3D is the RenderBuffer3D to be deleted.
*/
/*!
* \internal
*/
void CanvasContext::deleteRenderbuffer(QJSValue renderbuffer3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(renderbuffer3D:" << renderbuffer3D.toString()
<< ")";
CanvasRenderBuffer *renderbuffer = getAsRenderbuffer3D(renderbuffer3D);
if (renderbuffer) {
renderbuffer->del();
logAllGLErrors(__FUNCTION__);
} else {
m_error = INVALID_VALUE;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): INVALID_VALUE renderbuffer handle";
}
}
/*!
* \qmlmethod void Context3D::sampleCoverage(float value, bool invert)
* Sets the multisample coverage parameters.
* \a value specifies the floating-point sample coverage value. The value is clamped to the range
* \c{[0, 1]} with initial value of \c{1.0}.
* \a invert specifies if coverage masks should be inverted.
*/
/*!
* \internal
*/
void CanvasContext::sampleCoverage(float value, bool invert)
1961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(value:" << value
<< ", invert:" << invert
<< ")";
glSampleCoverage(value, invert);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod Program3D Context3D::createProgram()
* Returns a created Program3D object that is initialized with a program object name as if by
* calling \c{glCreateProgram()}.
*/
/*!
* \internal
*/
QJSValue CanvasContext::createProgram()
{
CanvasProgram *program = new CanvasProgram(this);
QJSValue value = m_engine->newQObject(program);
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "():" << value.toString();
logAllGLErrors(__FUNCTION__);
return value;
}
/*!
* \qmlmethod bool Context3D::isProgram(Object anyObject)
* Returns true if the given object is a valid Program3D object.
* \a anyObject is the object that is to be verified as a valid program.
*/
/*!
* \internal
*/
bool CanvasContext::isProgram(QJSValue anyObject) const
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(anyObject:" << anyObject.toString()
<< ")";
return (getAsProgram3D(anyObject) != Q_NULLPTR);
}
/*!
* \internal
*/
CanvasProgram *CanvasContext::getAsProgram3D(QJSValue anyObject) const
{
if (!anyObject.isQObject())
return 0;
if (!isOfType(anyObject, "QtCanvas3D::CanvasProgram"))
return 0;
CanvasProgram *program = static_cast<CanvasProgram *>(anyObject.toQObject());
if (!program->isAlive())
return 0;
return program;
}
/*!
* \qmlmethod void Context3D::deleteProgram(Program3D program3D)
* Deletes the given program as if by calling \c{glDeleteProgram()}.
* Calling this method repeatedly on the same object has no side effects.
* \a program3D is the Program3D to be deleted.
*/
/*!
2031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100
* \internal
*/
void CanvasContext::deleteProgram(QJSValue program3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ")";
CanvasProgram *program = getAsProgram3D(program3D);
if (program) {
program->del();
logAllGLErrors(__FUNCTION__);
} else {
m_error = INVALID_VALUE;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_VALUE program handle:" << program3D.toString();
}
}
/*!
* \qmlmethod void Context3D::attachShader(Program3D program3D, Shader3D shader3D)
* Attaches the given \a shader3D object to the given \a program3D object.
* Calling this method repeatedly on the same object has no side effects.
*/
/*!
* \internal
*/
void CanvasContext::attachShader(QJSValue program3D, QJSValue shader3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ", shader:" << shader3D.toString()
<< ")";
CanvasProgram *program = getAsProgram3D(program3D);
CanvasShader *shader = getAsShader3D(shader3D);
if (!program) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): Invalid program handle "
<< program3D.toString();
return;
}
if (!shader) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): Invalid shader handle "
<< shader3D.toString();
return;
}
program->attach(shader);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod list<Shader3D> Context3D::getAttachedShaders(Program3D program3D)
* Returns the list of shaders currently attached to the given \a program3D.
*/
/*!
* \internal
*/
QVariantList CanvasContext::getAttachedShaders(QJSValue program3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ")";
QVariantList shaderList;
2101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170
CanvasProgram *program = getAsProgram3D(program3D);
if (!program)
return shaderList;
QList<CanvasShader *> shaders = program->attachedShaders();
for (QList<CanvasShader *>::const_iterator iter = shaders.constBegin();
iter != shaders.constEnd(); iter++) {
CanvasShader *shader = *iter;
shaderList << QVariant::fromValue(shader);
}
return shaderList;
}
/*!
* \qmlmethod void Context3D::detachShader(Program3D program, Shader3D shader)
* Detaches given shader object from given program object.
* \a program3D specifies the program object from which to detach the shader.
* \a shader3D specifies the shader object to detach.
*/
/*!
* \internal
*/
void CanvasContext::detachShader(QJSValue program3D, QJSValue shader3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ", shader:" << shader3D.toString()
<< ")";
CanvasProgram *program = getAsProgram3D(program3D);
CanvasShader *shader = getAsShader3D(shader3D);
if (!program) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): Invalid program handle "
<< program3D.toString();
return;
}
if (!shader) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): Invalid shader handle "
<< shader3D.toString();
return;
}
program->detach(shader);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::linkProgram(Program3D program3D)
* Links the given program object.
* \a program3D specifies the program to be linked.
*/
/*!
* \internal
*/
void CanvasContext::linkProgram(QJSValue program3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ")";
CanvasProgram *program = getAsProgram3D(program3D);
2171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240
if (!program)
return;
program->link();
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::lineWidth(float width)
* Specifies the width of rasterized lines.
* \a width specifies the width to be used when rasterizing lines. Initial value is \c{1.0}.
*/
/*!
* \internal
*/
void CanvasContext::lineWidth(float width)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(width:" << width
<< ")";
glLineWidth(width);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::polygonOffset(float factor, float units)
* Sets scale and units used to calculate depth values.
* \a factor specifies the scale factor that is used to create a variable depth offset for each
* polygon. Initial value is \c{0.0}.
* \a units gets multiplied by an implementation-specific value to create a constant depth offset.
* Initial value is \c{0.0}.
*/
/*!
* \internal
*/
void CanvasContext::polygonOffset(float factor, float units)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(factor:" << factor
<< ", units:" << units
<< ")";
glPolygonOffset(factor, units);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::pixelStorei(glEnums pname, int param)
* Set the pixel storage modes.
* \a pname specifies the name of the parameter to be set. \c {Context3D.PACK_ALIGNMENT} affects the
* packing of pixel data into memory. \c {Context3D.UNPACK_ALIGNMENT} affects the unpacking of pixel
* data from memory. \c {Context3D.UNPACK_FLIP_Y_WEBGL} is initially \c false, but once set, in any
* subsequent calls to \l texImage2D or \l texSubImage2D, the source data is flipped along the
* vertical axis. \c {Context3D.UNPACK_PREMULTIPLY_ALPHA_WEBGL} is initially \c false, but once set,
* in any subsequent calls to \l texImage2D or \l texSubImage2D, the alpha channel of the source
* data, is multiplied into the color channels during the data transfer. Initial value is \c false
* and any non-zero value is interpreted as \c true.
*
* \a param specifies the value that \a pname is set to.
*/
/*!
* \internal
*/
void CanvasContext::pixelStorei(glEnums pname, int param)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(pname:" << glEnumToString(pname)
<< ", param:" << param
<< ")";
2241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310
switch (pname) {
case UNPACK_FLIP_Y_WEBGL:
m_unpackFlipYEnabled = (param != 0);
break;
case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
m_unpackPremultiplyAlphaEnabled = (param != 0);
break;
case UNPACK_COLORSPACE_CONVERSION_WEBGL:
// Intentionally ignored
break;
default:
glPixelStorei(GLenum(pname), param);
logAllGLErrors(__FUNCTION__);
break;
}
}
/*!
* \qmlmethod void Context3D::hint(glEnums target, glEnums mode)
* Set implementation-specific hints.
* \a target \c Context3D.GENERATE_MIPMAP_HINT is accepted.
* \a mode \c{Context3D.FASTEST}, \c{Context3D.NICEST}, and \c{Context3D.DONT_CARE} are accepted.
*/
/*!
* \internal
*/
void CanvasContext::hint(glEnums target, glEnums mode)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ",mode:" << glEnumToString(mode) << ")";
switch (target) {
case FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
if (m_standardDerivatives) {
glHint(GLenum(target), GLenum(mode));
logAllGLErrors(__FUNCTION__);
} else {
m_error = INVALID_ENUM;
}
break;
default:
glHint(GLenum(target), GLenum(mode));
logAllGLErrors(__FUNCTION__);
break;
}
}
/*!
* \qmlmethod void Context3D::enable(glEnums cap)
* Enable server side GL capabilities.
* \a cap specifies a constant indicating a GL capability.
*/
/*!
* \internal
*/
void CanvasContext::enable(glEnums cap)
{
QString str = QString(__FUNCTION__);
str += QStringLiteral("(cap:")
+ glEnumToString(cap)
+ QStringLiteral(")");
qCDebug(canvas3drendering).nospace() << str;
glEnable(cap);
logAllGLErrors(str);
}
/*!
* \qmlmethod bool Context3D::isEnabled(glEnums cap)
* Returns whether a capability is enabled.
2311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380
* \a cap specifies a constant indicating a GL capability.
*/
/*!
* \internal
*/
bool CanvasContext::isEnabled(glEnums cap)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(cap:" << glEnumToString(cap)
<< ")";
return glIsEnabled(cap);
}
/*!
* \qmlmethod void Context3D::disable(glEnums cap)
* Disable server side GL capabilities.
* \a cap specifies a constant indicating a GL capability.
*/
/*!
* \internal
*/
void CanvasContext::disable(glEnums cap)
{
QString str = QString(__FUNCTION__);
str += QStringLiteral("(cap:")
+ glEnumToString(cap)
+ QStringLiteral(")");
qCDebug(canvas3drendering).nospace() << str;
glDisable(cap);
logAllGLErrors(str);
}
/*!
* \qmlmethod void Context3D::blendColor(float red, float green, float blue, float alpha)
* Set the blend color.
* \a red, \a green, \a blue and \a alpha specify the components of \c{Context3D.BLEND_COLOR}.
*/
/*!
* \internal
*/
void CanvasContext::blendColor(float red, float green, float blue, float alpha)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(red:" << red
<< ", green:" << green
<< ", blue:" << blue
<< ", alpha:" << alpha
<< ")";
glBlendColor(red, green, blue, alpha);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::blendEquation(glEnums mode)
* Sets the equation used for both the RGB blend equation and the alpha blend equation
* \a mode specifies how source and destination colors are to be combined. Must be
* \c{Context3D.FUNC_ADD}, \c{Context3D.FUNC_SUBTRACT} or \c{Context3D.FUNC_REVERSE_SUBTRACT}.
*/
/*!
* \internal
*/
void CanvasContext::blendEquation(glEnums mode)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(mode:" << glEnumToString(mode)
<< ")";
glBlendEquation(GLenum(mode));
logAllGLErrors(__FUNCTION__);
}
2381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450
/*!
* \qmlmethod void Context3D::blendEquationSeparate(glEnums modeRGB, glEnums modeAlpha)
* Set the RGB blend equation and the alpha blend equation separately.
* \a modeRGB specifies how the RGB components of the source and destination colors are to be
* combined. Must be \c{Context3D.FUNC_ADD}, \c{Context3D.FUNC_SUBTRACT} or
* \c{Context3D.FUNC_REVERSE_SUBTRACT}.
* \a modeAlpha specifies how the alpha component of the source and destination colors are to be
* combined. Must be \c{Context3D.FUNC_ADD}, \c{Context3D.FUNC_SUBTRACT}, or
* \c{Context3D.FUNC_REVERSE_SUBTRACT}.
*/
/*!
* \internal
*/
void CanvasContext::blendEquationSeparate(glEnums modeRGB, glEnums modeAlpha)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(modeRGB:" << glEnumToString(modeRGB)
<< ", modeAlpha:" << glEnumToString(modeAlpha)
<< ")";
glBlendEquationSeparate(GLenum(modeRGB), GLenum(modeAlpha));
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::blendFunc(glEnums sfactor, glEnums dfactor)
* Sets the pixel arithmetic.
* \a sfactor specifies how the RGBA source blending factors are computed. Must be
* \c{Context3D.ZERO}, \c{Context3D.ONE}, \c{Context3D.SRC_COLOR},
* \c{Context3D.ONE_MINUS_SRC_COLOR},
* \c{Context3D.DST_COLOR}, \c{Context3D.ONE_MINUS_DST_COLOR}, \c{Context3D.SRC_ALPHA},
* \c{Context3D.ONE_MINUS_SRC_ALPHA}, \c{Context3D.DST_ALPHA}, \c{Context3D.ONE_MINUS_DST_ALPHA},
* \c{Context3D.CONSTANT_COLOR}, \c{Context3D.ONE_MINUS_CONSTANT_COLOR},
* \c{Context3D.CONSTANT_ALPHA},
* \c{Context3D.ONE_MINUS_CONSTANT_ALPHA} or \c{Context3D.SRC_ALPHA_SATURATE}. Initial value is
* \c{Context3D.ONE}.
* \a dfactor Specifies how the RGBA destination blending factors are computed. Must be
* \c{Context3D.ZERO}, \c{Context3D.ONE}, \c{Context3D.SRC_COLOR},
* \c{Context3D.ONE_MINUS_SRC_COLOR},
* \c{Context3D.DST_COLOR}, \c{Context3D.ONE_MINUS_DST_COLOR}, \c{Context3D.SRC_ALPHA},
* \c{Context3D.ONE_MINUS_SRC_ALPHA}, \c{Context3D.DST_ALPHA}, \c{Context3D.ONE_MINUS_DST_ALPHA},
* \c{Context3D.CONSTANT_COLOR}, \c{Context3D.ONE_MINUS_CONSTANT_COLOR},
* \c{Context3D.CONSTANT_ALPHA} or
* \c{Context3D.ONE_MINUS_CONSTANT_ALPHA}. Initial value is \c{Context3D.ZERO}.
*/
/*!
* \internal
*/
void CanvasContext::blendFunc(glEnums sfactor, glEnums dfactor)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(sfactor:" << glEnumToString(sfactor)
<< ", dfactor:" << glEnumToString(dfactor)
<< ")";
if (((sfactor == CONSTANT_COLOR || sfactor == ONE_MINUS_CONSTANT_COLOR)
&& (dfactor == CONSTANT_ALPHA || dfactor == ONE_MINUS_CONSTANT_ALPHA))
|| ((dfactor == CONSTANT_COLOR || dfactor == ONE_MINUS_CONSTANT_COLOR)
&& (sfactor == CONSTANT_ALPHA || sfactor == ONE_MINUS_CONSTANT_ALPHA))) {
m_error = INVALID_OPERATION;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_OPERATION illegal combination";
return;
}
glBlendFunc(GLenum(sfactor), GLenum(dfactor));
logAllGLErrors(__FUNCTION__);
}
/*!
2451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520
* \qmlmethod void Context3D::blendFuncSeparate(glEnums srcRGB, glEnums dstRGB, glEnums srcAlpha, glEnums dstAlpha)
* Sets the pixel arithmetic for RGB and alpha components separately.
* \a srcRGB specifies how the RGB source blending factors are computed. Must be \c{Context3D.ZERO},
* \c{Context3D.ONE}, \c{Context3D.SRC_COLOR}, \c{Context3D.ONE_MINUS_SRC_COLOR},
* \c{Context3D.DST_COLOR},
* \c{Context3D.ONE_MINUS_DST_COLOR}, \c{Context3D.SRC_ALPHA}, \c{Context3D.ONE_MINUS_SRC_ALPHA},
* \c{Context3D.DST_ALPHA}, \c{Context3D.ONE_MINUS_DST_ALPHA}, \c{Context3D.CONSTANT_COLOR},
* \c{Context3D.ONE_MINUS_CONSTANT_COLOR}, \c{Context3D.CONSTANT_ALPHA},
* \c{Context3D.ONE_MINUS_CONSTANT_ALPHA} or \c{Context3D.SRC_ALPHA_SATURATE}. Initial value is
* \c{Context3D.ONE}.
* \a dstRGB Specifies how the RGB destination blending factors are computed. Must be
* \c{Context3D.ZERO}, \c{Context3D.ONE}, \c{Context3D.SRC_COLOR}, \c{Context3D.ONE_MINUS_SRC_COLOR},
* \c{Context3D.DST_COLOR}, \c{Context3D.ONE_MINUS_DST_COLOR}, \c{Context3D.SRC_ALPHA},
* \c{Context3D.ONE_MINUS_SRC_ALPHA}, \c{Context3D.DST_ALPHA}, \c{Context3D.ONE_MINUS_DST_ALPHA},
* \c{Context3D.CONSTANT_COLOR}, \c{Context3D.ONE_MINUS_CONSTANT_COLOR},
* \c{Context3D.CONSTANT_ALPHA} or
* \c{Context3D.ONE_MINUS_CONSTANT_ALPHA}. Initial value is \c{Context3D.ZERO}.
* \a srcAlpha specifies how the alpha source blending factors are computed. Must be
* \c{Context3D.ZERO}, \c{Context3D.ONE}, \c{Context3D.SRC_COLOR},
* \c{Context3D.ONE_MINUS_SRC_COLOR},
* \c{Context3D.DST_COLOR}, \c{Context3D.ONE_MINUS_DST_COLOR}, \c{Context3D.SRC_ALPHA},
* \c{Context3D.ONE_MINUS_SRC_ALPHA}, \c{Context3D.DST_ALPHA}, \c{Context3D.ONE_MINUS_DST_ALPHA},
* \c{Context3D.CONSTANT_COLOR}, \c{Context3D.ONE_MINUS_CONSTANT_COLOR},
* \c{Context3D.CONSTANT_ALPHA},
* \c{Context3D.ONE_MINUS_CONSTANT_ALPHA} or \c{Context3D.SRC_ALPHA_SATURATE}. Initial value is
* \c{Context3D.ONE}.
* \a dstAlpha Specifies how the alpha destination blending factors are computed. Must be
* \c{Context3D.ZERO}, \c{Context3D.ONE}, \c{Context3D.SRC_COLOR},
* \c{Context3D.ONE_MINUS_SRC_COLOR},
* \c{Context3D.DST_COLOR}, \c{Context3D.ONE_MINUS_DST_COLOR}, \c{Context3D.SRC_ALPHA},
* \c{Context3D.ONE_MINUS_SRC_ALPHA}, \c{Context3D.DST_ALPHA}, \c{Context3D.ONE_MINUS_DST_ALPHA},
* \c{Context3D.CONSTANT_COLOR}, \c{Context3D.ONE_MINUS_CONSTANT_COLOR},
* \c{Context3D.CONSTANT_ALPHA} or
* \c{Context3D.ONE_MINUS_CONSTANT_ALPHA}. Initial value is \c{Context3D.ZERO}.
*/
/*!
* \internal
*/
void CanvasContext::blendFuncSeparate(glEnums srcRGB, glEnums dstRGB, glEnums srcAlpha,
glEnums dstAlpha)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(srcRGB:" << glEnumToString(srcRGB)
<< ", dstRGB:" << glEnumToString(dstRGB)
<< ", srcAlpha:" << glEnumToString(srcAlpha)
<< ", dstAlpha:" << glEnumToString(dstAlpha)
<< ")";
if (((srcRGB == CONSTANT_COLOR || srcRGB == ONE_MINUS_CONSTANT_COLOR )
&& (dstRGB == CONSTANT_ALPHA || dstRGB == ONE_MINUS_CONSTANT_ALPHA ))
|| ((dstRGB == CONSTANT_COLOR || dstRGB == ONE_MINUS_CONSTANT_COLOR )
&& (srcRGB == CONSTANT_ALPHA || srcRGB == ONE_MINUS_CONSTANT_ALPHA ))) {
m_error = INVALID_OPERATION;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_OPERATION illegal combination";
return;
}
glBlendFuncSeparate(GLenum(srcRGB), GLenum(dstRGB), GLenum(srcAlpha), GLenum(dstAlpha));
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod variant Context3D::getProgramParameter(Program3D program3D, glEnums paramName)
* Return the value for the passed \a paramName given the passed \a program3D. The type returned is
* the natural type for the requested paramName.
* \a paramName must be \c{Context3D.DELETE_STATUS}, \c{Context3D.LINK_STATUS},
* \c{Context3D.VALIDATE_STATUS}, \c{Context3D.ATTACHED_SHADERS}, \c{Context3D.ACTIVE_ATTRIBUTES} or
* \c{Context3D.ACTIVE_UNIFORMS}.
*/
2521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590
/*!
* \internal
*/
QVariant CanvasContext::getProgramParameter(QJSValue program3D, glEnums paramName)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ", paramName:" << glEnumToString(paramName)
<< ")";
CanvasProgram *program = getAsProgram3D(program3D);
if (!program)
return 0;
switch(paramName) {
case DELETE_STATUS:
// Intentional flow through
case LINK_STATUS:
// Intentional flow through
case VALIDATE_STATUS: {
GLint value = 0;
glGetProgramiv(program->id(), GLenum(paramName), &value);
logAllGLErrors(__FUNCTION__);
qCDebug(canvas3drendering).nospace() << " getProgramParameter returns " << value;
return QVariant::fromValue(value == GL_TRUE);
}
case ATTACHED_SHADERS:
// Intentional flow through
case ACTIVE_ATTRIBUTES:
// Intentional flow through
case ACTIVE_UNIFORMS: {
GLint value = 0;
glGetProgramiv(program->id(), GLenum(paramName), &value);
logAllGLErrors(__FUNCTION__);
qCDebug(canvas3drendering).nospace() << " getProgramParameter returns " << value;
return QVariant::fromValue(value);
}
default: {
m_error = INVALID_ENUM;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_ENUM illegal parameter name ";
return QVariant::fromValue(0);
}
}
}
/*!
* \qmlmethod Shader3D Context3D::createShader(glEnums type)
* Creates a shader of \a type. Must be either \c Context3D.VERTEX_SHADER or
* \c{Context3D.FRAGMENT_SHADER}.
*/
/*!
* \internal
*/
QJSValue CanvasContext::createShader(glEnums type)
{
switch (type) {
case VERTEX_SHADER:
qCDebug(canvas3drendering).nospace() << "Context3D::createShader(VERTEX_SHADER)";
return m_engine->newQObject(new CanvasShader(QOpenGLShader::Vertex, this));
case FRAGMENT_SHADER:
qCDebug(canvas3drendering).nospace() << "Context3D::createShader(FRAGMENT_SHADER)";
return m_engine->newQObject(new CanvasShader(QOpenGLShader::Fragment, this));
default:
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM unknown shader type:"
<< glEnumToString(type);
m_error = INVALID_ENUM;
return m_engine->newObject();
2591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660
}
}
/*!
* \qmlmethod bool Context3D::isShader(Object anyObject)
* Returns true if the given object is a valid Shader3D object.
* \a anyObject is the object that is to be verified as a valid shader.
*/
/*!
* \internal
*/
bool CanvasContext::isShader(QJSValue anyObject)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(anyObject:" << anyObject.toString()
<< ")";
CanvasShader *shader3D = getAsShader3D(anyObject);
if (!shader3D)
return false;
return glIsShader(shader3D->id());
}
/*!
* \internal
*/
CanvasShader *CanvasContext::getAsShader3D(QJSValue shader3D) const
{
if (!isOfType(shader3D, "QtCanvas3D::CanvasShader"))
return 0;
CanvasShader *shader = static_cast<CanvasShader *>(shader3D.toQObject());
if (!shader->isAlive())
return 0;
return shader;
}
/*!
* \qmlmethod void Context3D::deleteShader(Shader3D shader)
* Deletes the given shader as if by calling \c{glDeleteShader()}.
* Calling this method repeatedly on the same object has no side effects.
* \a shader is the Shader3D to be deleted.
*/
/*!
* \internal
*/
void CanvasContext::deleteShader(QJSValue shader3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::"
<< __FUNCTION__
<< "(shader:" << shader3D.toString()
<< ")";
CanvasShader *shader = getAsShader3D(shader3D);
if (shader) {
shader->del();
logAllGLErrors(__FUNCTION__);
} else {
m_error = INVALID_VALUE;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": invalid shader handle:" << shader3D.toString();
}
}
/*!
* \qmlmethod void Context3D::shaderSource(Shader3D shader, string shaderSource)
* Replaces the shader source code in the given shader object.
2661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730
* \a shader specifies the shader object whose source code is to be replaced.
* \a shaderSource specifies the source code to be loaded in to the shader.
*/
/*!
* \internal
*/
void CanvasContext::shaderSource(QJSValue shader3D, const QString &shaderSource)
{
QString modSource = "#version 120 \n#define precision \n"+ shaderSource;
if (m_isOpenGLES2)
modSource = shaderSource;
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(shader:" << shader3D.toString()
<< ", shaderSource"
<< ")" << endl << modSource << endl;
CanvasShader *shader = getAsShader3D(shader3D);
if (!shader) {
m_error = INVALID_VALUE;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": invalid shader handle:" << shader3D.toString();
return;
}
shader->setSourceCode(modSource);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod string Context3D::getShaderSource(Shader3D shader)
* Returns the source code string from the \a shader object.
*/
/*!
* \internal
*/
QJSValue CanvasContext::getShaderSource(QJSValue shader3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(shader:" << shader3D.toString()
<< ")";
CanvasShader *shader = getAsShader3D(shader3D);
if (!shader) {
m_error = INVALID_VALUE;
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<<": invalid shader handle:" << shader3D.toString();
return m_engine->newObject();
}
return QJSValue(QString(shader->qOGLShader()->sourceCode()));
}
/*!
* \qmlmethod void Context3D::compileShader(Shader3D shader)
* Compiles the given \a shader object.
*/
/*!
* \internal
*/
void CanvasContext::compileShader(QJSValue shader3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(shader:" << shader3D.toString()
<< ")";
CanvasShader *shader = getAsShader3D(shader3D);
if (!shader) {
m_error = INVALID_VALUE;
2731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": invalid shader handle:" << shader3D.toString();
return;
}
shader->qOGLShader()->compileSourceCode(shader->sourceCode());
logAllGLErrors(__FUNCTION__);
}
/*!
* \internal
*/
CanvasUniformLocation *CanvasContext::getAsUniformLocation3D(QJSValue anyObject) const
{
if (!isOfType(anyObject, "QtCanvas3D::CanvasUniformLocation"))
return 0;
CanvasUniformLocation *uniformLocation =
static_cast<CanvasUniformLocation *>(anyObject.toQObject());
// TODO: Should uniform locations be killed and checked for "isAlive" when program is
// deleted?
return uniformLocation;
}
/*!
* \qmlmethod void Context3D::uniform1i(UniformLocation3D location3D, int x)
* Sets the single integer value given in \a x to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform1i(QJSValue location3D, int x)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", x:" << x
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
glUniform1i(locationObj->id(), x);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform1iv(UniformLocation3D location3D, Int32Array array)
* Sets the integer array given in \a array to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform1iv(QJSValue location3D, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", array:" << array.toString()
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
// Check if we have a JavaScript array
if (array.isArray()) {
uniform1fva(locationObj, array.toVariant().toList());
return;
2801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Int32Array)
return;
glUniform1iv(locationObj->id(),
typedArray->length(),
(int *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform1f(UniformLocation3D location3D, float x)
* Sets the single float value given in \a x to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform1f(QJSValue location3D, float x)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", x:" << x
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
glUniform1f(locationObj->id(), x);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform1fvt(UniformLocation3D location3D, Object array)
* Sets the float array given in \a array to the given uniform \a location3D. \a array must be
* a JavaScript \c Array object or a \c Float32Array object.
*/
/*!
* \internal
*/
void CanvasContext::uniform1fv(QJSValue location3D, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", array:" << array.toString()
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
// Check if we have a JavaScript array
if (array.isArray()) {
uniform1fva(locationObj, array.toVariant().toList());
return;
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array)
2871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940
return;
glUniform1fv(locationObj->id(),
typedArray->length(),
(float *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform2f(UniformLocation3D location3D, float x, float y)
* Sets the two float values given in \a x and \a y to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform2f(QJSValue location3D, float x, float y)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", x:" << x
<< ", y:" << y
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
glUniform2f(locationObj->id(), x, y);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform2fv(UniformLocation3D location3D, Float32Array array)
* Sets the float array given in \a array to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform2fv(QJSValue location3D, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", array:" << array.toString()
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
// Check if we have a JavaScript array
if (array.isArray()) {
uniform2fva(locationObj, array.toVariant().toList());
return;
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array)
return;
glUniform2fv(locationObj->id(),
typedArray->length() / 2,
(float *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
2941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010
/*!
* \qmlmethod void Context3D::uniform2i(UniformLocation3D location3D, int x, int y)
* Sets the two integer values given in \a x and \a y to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform2i(QJSValue location3D, int x, int y)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", x:" << x
<< ", y:" << y
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
glUniform2i(locationObj->id(), x, y);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform2iv(UniformLocation3D location3D, Int32Array array)
* Sets the integer array given in \a array to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform2iv(QJSValue location3D, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", array:" << array.toString()
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
// Check if we have a JavaScript array
if (array.isArray()) {
uniform2iva(locationObj, array.toVariant().toList());
return;
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Int32Array)
return;
glUniform2iv(locationObj->id(),
typedArray->length() / 2,
(int *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform3f(UniformLocation3D location3D, float x, float y, float z)
* Sets the three float values given in \a x , \a y and \a z to the given uniform \a location3D.
*/
/*!
* \internal
*/
3011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080
void CanvasContext::uniform3f(QJSValue location3D, float x, float y, float z)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", x:" << x
<< ", y:" << y
<< ", z:" << z
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
glUniform3f(locationObj->id(), x, y, z);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform3fv(UniformLocation3D location3D, Float32Array array)
* Sets the float array given in \a array to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform3fv(QJSValue location3D, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", array:" << array.toString()
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
// Check if we have a JavaScript array
if (array.isArray()) {
uniform3fva(locationObj, array.toVariant().toList());
return;
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) {
return;
}
glUniform3fv(locationObj->id(),
typedArray->length() / 3,
(float *) typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform3i(UniformLocation3D location3D, int x, int y, int z)
* Sets the three integer values given in \a x , \a y and \a z to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform3i(QJSValue location3D, int x, int y, int z)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", x:" << x
<< ", y:" << y
<< ", z:" << z
3081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
glUniform3i(locationObj->id(), x, y, z);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform3iv(UniformLocation3D location3D, Int32Array array)
* Sets the integer array given in \a array to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform3iv(QJSValue location3D, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", array:" << array.toString()
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
// Check if we have a JavaScript array
if (array.isArray()) {
uniform3iva(locationObj, array.toVariant().toList());
return;
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Int32Array) {
return;
}
glUniform3iv(locationObj->id(),
typedArray->length() / 3,
(int *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform4f(UniformLocation3D location3D, float x, float y, float z, float w)
* Sets the four float values given in \a x , \a y , \a z and \a w to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform4f(QJSValue location3D, float x, float y, float z, float w)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", x:" << x
<< ", y:" << y
<< ", z:" << z
<< ", w:" << w
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
glUniform4f(locationObj->id(), x, y, z, w);
logAllGLErrors(__FUNCTION__);
3151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220
}
/*!
* \qmlmethod void Context3D::uniform4fv(UniformLocation3D location3D, Float32Array array)
* Sets the float array given in \a array to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform4fv(QJSValue location3D, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", array:" << array.toString()
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
// Check if we have a JavaScript array
if (array.isArray()) {
uniform4fva(locationObj, array.toVariant().toList());
return;
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array)
return;
glUniform4fv(locationObj->id(),
typedArray->length() / 4,
(float *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform4i(UniformLocation3D location3D, int x, int y, int z, int w)
* Sets the four integer values given in \a x , \a y , \a z and \a w to the given uniform
* \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform4i(QJSValue location3D, int x, int y, int z, int w)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", x:" << x
<< ", y:" << y
<< ", z:" << z
<< ", w:" << w
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
glUniform4i(locationObj->id(), x, y, z, w);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniform4iv(UniformLocation3D location3D, Int32Array array)
* Sets the integer array given in \a array to the given uniform \a location3D.
*/
/*!
3221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290
* \internal
*/
void CanvasContext::uniform4iv(QJSValue location3D, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", array:" << array.toString()
<< ")";
CanvasUniformLocation *locationObj = getAsUniformLocation3D(location3D);
if (!locationObj)
return;
// Check if we have a JavaScript array
if (array.isArray()) {
uniform4iva(locationObj, array.toVariant().toList());
return;
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Int32Array)
return;
glUniform4iv(locationObj->id(),
typedArray->length() / 4,
(int *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \internal
*/
void CanvasContext::uniform1fva(CanvasUniformLocation *location3D, QVariantList array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D
<< ", array:" << array
<< ")";
float *arrayData = new float[array.length()];
ArrayUtils::fillFloatArrayFromVariantList(array, arrayData);
glUniform1fv(location3D->id(), array.count(), arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \internal
*/
void CanvasContext::uniform2fva(CanvasUniformLocation *location3D, QVariantList array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D
<< ", array:" << array
<< ")";
float *arrayData = new float[array.length()];
ArrayUtils::fillFloatArrayFromVariantList(array, arrayData);
glUniform2fv(location3D->id(), array.count() / 2, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \internal
*/
void CanvasContext::uniform3fva(CanvasUniformLocation *location3D, QVariantList array)
3291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D
<< ", array:" << array
<< ")";
float *arrayData = new float[array.length()];
ArrayUtils::fillFloatArrayFromVariantList(array, arrayData);
glUniform3fv(location3D->id(), array.count() / 3, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \internal
*/
void CanvasContext::uniform4fva(CanvasUniformLocation *location3D, QVariantList array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D
<< ", array:" << array
<< ")";
float *arrayData = new float[array.count()];
ArrayUtils::fillFloatArrayFromVariantList(array, arrayData);
glUniform4fv(location3D->id(), array.count() / 4, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \internal
*/
void CanvasContext::uniform1iva(CanvasUniformLocation *location3D, QVariantList array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D
<< ", array:" << array
<< ")";
int *arrayData = new int[array.length()];
ArrayUtils::fillIntArrayFromVariantList(array, arrayData);
glUniform1iv(location3D->id(), array.count(), arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \internal
*/
void CanvasContext::uniform2iva(CanvasUniformLocation *location3D, QVariantList array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D
<< ", array:" << array
<< ")";
int *arrayData = new int[array.length()];
ArrayUtils::fillIntArrayFromVariantList(array, arrayData);
glUniform2iv(location3D->id(), array.count() / 2, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \internal
*/
void CanvasContext::uniform3iva(CanvasUniformLocation *location3D, QVariantList array)
{
3361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D
<< ", array:" << array
<< ")";
int *arrayData = new int[array.length()];
ArrayUtils::fillIntArrayFromVariantList(array, arrayData);
glUniform3iv(location3D->id(), array.count() / 3, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \qmlmethod void Context3D::uniform4iva(UniformLocation3D location3D, list<variant> array)
* Sets the integer array given as JavasScript \a array to the given uniform \a location3D.
*/
/*!
* \internal
*/
void CanvasContext::uniform4iva(CanvasUniformLocation *location3D, QVariantList array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D
<< ", array:" << array
<< ")";
int *arrayData = new int[array.length()];
ArrayUtils::fillIntArrayFromVariantList(array, arrayData);
glUniform4iv(location3D->id(), array.length() / 4, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \qmlmethod void Context3D::vertexAttrib1f(int indx, float x)
* Sets the single float value given in \a x to the generic vertex attribute index specified
* by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib1f(unsigned int indx, float x)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx:" << indx
<< ", x:" << x
<< ")";
glVertexAttrib1f(indx, x);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::vertexAttrib1fv(int indx, Float32Array array)
* Sets the float array given in \a array to the generic vertex attribute index
* specified by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib1fv(unsigned int indx, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx:" << indx
<< ", array:" << array.toString()
<< ")";
// Check if we have a JavaScript array
if (array.isArray()) {
vertexAttrib1fva(indx, array.toVariant().toList());
3431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500
return;
}
// Check if we have a Float32Array
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array)
return;
glVertexAttrib1fv(indx, (float *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::vertexAttrib2f(int indx, float x, float y)
* Sets the two float values given in \a x and \a y to the generic vertex attribute index
* specified by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib2f(unsigned int indx, float x, float y)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx:" << indx
<< ", x:" << x
<< ", y:" << y
<< ")";
glVertexAttrib2f(indx, x, y);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::vertexAttrib2fv(int indx, Float32Array array)
* Sets the float array given in \a array to the generic vertex attribute index
* specified by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib2fv(unsigned int indx, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx:" << indx
<< ", array:" << array.toString()
<< ")";
// Check if we have a JavaScript array
if (array.isArray()) {
vertexAttrib2fva(indx, array.toVariant().toList());
return;
}
// Check if we have a Float32Array
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array)
return;
glVertexAttrib2fv(indx, (float *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::vertexAttrib3f(int indx, float x, float y, float z)
* Sets the three float values given in \a x , \a y and \a z to the generic vertex attribute index
* specified by \a indx.
*/
3501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570
/*!
* \internal
*/
void CanvasContext::vertexAttrib3f(unsigned int indx, float x, float y, float z)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx:" << indx
<< ", x:" << x
<< ", y:" << y
<< ", z:" << z
<< ")";
glVertexAttrib3f(indx, x, y, z);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::vertexAttrib3fv(int indx, Float32Array array)
* Sets the float array given in \a array to the generic vertex attribute index
* specified by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib3fv(unsigned int indx, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx:" << indx
<< ", array:" << array.toString()
<< ")";
// Check if we have a JavaScript array
if (array.isArray()) {
vertexAttrib3fva(indx, array.toVariant().toList());
return;
}
// Check if we have a Float32Array
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array)
return;
glVertexAttrib3fv(indx, (float *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::vertexAttrib4f(int indx, float x, float y, float z, float w)
* Sets the four float values given in \a x , \a y , \a z and \a w to the generic vertex attribute
* index specified by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib4f(unsigned int indx, float x, float y, float z, float w)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx:" << indx
<< ", x:" << x
<< ", y:" << y
<< ", z:" << z
<< ", w:" << w
<< ")";
glVertexAttrib4f(indx, x, y, z, w);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::vertexAttrib4fv(int indx, Float32Array array)
3571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640
* Sets the float array given in \a array to the generic vertex attribute index
* specified by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib4fv(unsigned int indx, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx:" << indx
<< ", array:" << array.toString()
<< ")";
// Check if we have a JavaScript array
if (array.isArray()) {
vertexAttrib4fva(indx, array.toVariant().toList());
return;
}
// Check if we have a Float32Array
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!typedArray || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array)
return;
glVertexAttrib4fv(indx, (float *)typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod int Context3D::getShaderParameter(Shader3D shader, glEnums pname)
* Returns the value of the passed \a pname for the given \a shader.
* \a pname must be one of \c{Context3D.SHADER_TYPE}, \c Context3D.DELETE_STATUS and
* \c{Context3D.COMPILE_STATUS}.
*/
/*!
* \internal
*/
int CanvasContext::getShaderParameter(QJSValue shader3D, glEnums pname)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(shader:" << shader3D.toString()
<< ", pname:"<< glEnumToString(pname)
<< ")";
CanvasShader *shader = getAsShader3D(shader3D);
if (!shader) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<<": invalid shader handle:" << shader3D.toString();
return 0;
}
switch (pname) {
case SHADER_TYPE: {
GLint shaderType = 0;
glGetShaderiv( shader->qOGLShader()->shaderId(), GL_SHADER_TYPE, &shaderType);
logAllGLErrors(__FUNCTION__);
return shaderType;
}
case DELETE_STATUS: {
bool isDeleted = !shader->isAlive();
qCDebug(canvas3drendering).nospace() << " getShaderParameter returns " << isDeleted;
return (isDeleted ? GL_TRUE : GL_FALSE);
}
case COMPILE_STATUS: {
bool isCompiled = shader->qOGLShader()->isCompiled();
qCDebug(canvas3drendering).nospace() << " getShaderParameter returns " << isCompiled;
return (isCompiled ? GL_TRUE : GL_FALSE);
}
default: {
3641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710
qCWarning(canvas3drendering) << "getShaderParameter() : UNSUPPORTED parameter name "
<< glEnumToString(pname);
return 0;
}
}
}
/*!
* \qmlmethod Buffer3D Context3D::createBuffer()
* Creates a Buffer3D object and initializes it with a buffer object name as if \c glGenBuffers()
* was called.
*/
/*!
* \internal
*/
QJSValue CanvasContext::createBuffer()
{
CanvasBuffer *newBuffer = new CanvasBuffer(this);
logAllGLErrors(__FUNCTION__);
m_idToCanvasBufferMap[newBuffer->id()] = newBuffer;
QJSValue value = m_engine->newQObject(newBuffer);
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< ":" << value.toString() << " = " << newBuffer;
return value;
}
/*!
* \qmlmethod UniformLocation3D Context3D::getUniformLocation(Program3D program3D, string name)
* Returns UniformLocation3D object that represents the location3D of a specific uniform variable
* with the given \a name within the given \a program3D object.
* Returns \c null if name doesn't correspond to a uniform variable.
*/
/*!
* \internal
*/
QJSValue CanvasContext::getUniformLocation(QJSValue program3D, const QString &name)
{
CanvasProgram *program = getAsProgram3D(program3D);
if (!program) {
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ", name:" << name
<< "):-1";
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "WARNING: Invalid Program3D reference " << program;
return 0;
}
int index = program->uniformLocation(name);
logAllGLErrors(__FUNCTION__);
if (index < 0) {
return 0;
}
CanvasUniformLocation *location3D = new CanvasUniformLocation(index, this);
location3D->setName(name);
QJSValue value = m_engine->newQObject(location3D);
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ", name:" << value.toString()
<< "):" << location3D;
return value;
}
/*!
* \qmlmethod int Context3D::getAttribLocation(Program3D program3D, string name)
* Returns location3D of the given attribute variable \a name in the given \a program3D.
*/
3711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780
/*!
* \internal
*/
int CanvasContext::getAttribLocation(QJSValue program3D, const QString &name)
{
CanvasProgram *program = getAsProgram3D(program3D);
if (!program) {
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ", name:" << name
<< "):-1";
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID Program3D reference " << program;
return -1;
} else {
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ", name:" << name
<< "):" << program->attributeLocation(name);
}
return program->attributeLocation(name);
}
/*!
* \qmlmethod void Context3D::bindAttribLocation(Program3D program3D, int index, string name)
* Binds the attribute \a index with the attribute variable \a name in the given \a program3D.
*/
/*!
* \internal
*/
void CanvasContext::bindAttribLocation(QJSValue program3D, int index, const QString &name)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ", index:" << index
<< ", name:" << name
<< ")";
CanvasProgram *program = getAsProgram3D(program3D);
if (!program) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID Program3D reference " << program;
return;
}
program->bindAttributeLocation(index, name);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::enableVertexAttribArray(int index)
* Enables the vertex attribute array at \a index.
*/
/*!
* \internal
*/
void CanvasContext::enableVertexAttribArray(int index)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(index:" << index
<< ")";
glEnableVertexAttribArray(index);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::disableVertexAttribArray(int index)
* Disables the vertex attribute array at \a index.
*/
3781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850
/*!
* \internal
*/
void CanvasContext::disableVertexAttribArray(int index)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(index:" << index
<< ")";
glDisableVertexAttribArray(index);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniformMatrix2fv(UniformLocation3D location3D, bool transpose, Value array)
* Converts the float array given in \a array to a 2x2 matrix and sets it to the given
* uniform at \a uniformLocation. Applies \a transpose if set to \c{true}.
*/
/*!
* \internal
*/
void CanvasContext::uniformMatrix2fv(QJSValue location3D, bool transpose, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(uniformLocation:" << location3D.toString()
<< ", transpose:" << transpose
<< ", array:" << array.toString()
<<")";
if (!isOfType(location3D, "QtCanvas3D::CanvasUniformLocation"))
return;
CanvasUniformLocation *locationObj =
static_cast<CanvasUniformLocation *>(location3D.toQObject());
// Check if we have a JavaScript array
if (array.isArray()) {
uniformMatrix2fva(locationObj, transpose, array.toVariant().toList());
return;
}
// We should have a Float32Array
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!m_currentProgram
|| !typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array)
return;
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "numMatrices:" << (typedArray->length() / 4);
int uniformLocation = locationObj->id();
float *arrayData = (float *)typedArray->arrayData()->data();
int numMatrices = typedArray->length() / 4;
glUniformMatrix2fv(uniformLocation, numMatrices, transpose, arrayData);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniformMatrix3fv(UniformLocation3D location3D, bool transpose, Value array)
* Converts the float array given in \a array to a 3x3 matrix and sets it to the given
* uniform at \a uniformLocation. Applies \a transpose if set to \c{true}.
*/
/*!
* \internal
*/
void CanvasContext::uniformMatrix3fv(QJSValue location3D, bool transpose, QJSValue array)
{
3851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", transpose:" << transpose
<< ", array:" << array.toString()
<<")";
if (!isOfType(location3D, "QtCanvas3D::CanvasUniformLocation"))
return;
CanvasUniformLocation *locationObj =
static_cast<CanvasUniformLocation *>(location3D.toQObject());
// Check if we have a JavaScript array
if (array.isArray()) {
uniformMatrix3fva(locationObj, transpose, array.toVariant().toList());
return;
}
// We should have a Float32Array
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
if (!m_currentProgram
|| !typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array)
return;
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "numMatrices:" << (typedArray->length() / 9);
int uniformLocation = locationObj->id();
float *arrayData = (float *)typedArray->arrayData()->data();
int numMatrices = typedArray->length() / 9;
glUniformMatrix3fv(uniformLocation, numMatrices, transpose, arrayData);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::uniformMatrix4fv(UniformLocation3D location3D, bool transpose, Value array)
* Converts the float array given in \a array to a 4x4 matrix and sets it to the given
* uniform at \a uniformLocation. Applies \a transpose if set to \c{true}.
*/
/*!
* \internal
*/
void CanvasContext::uniformMatrix4fv(QJSValue location3D, bool transpose, QJSValue array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << location3D.toString()
<< ", transpose:" << transpose
<< ", array:" << array.toString()
<< ")";
if (!isOfType(location3D, "QtCanvas3D::CanvasUniformLocation"))
return;
CanvasUniformLocation *locationObj =
static_cast<CanvasUniformLocation *>(location3D.toQObject());
// Check if we have a JavaScript array
if (array.isArray()) {
uniformMatrix4fva(locationObj, transpose,array.toVariant().toList());
return;
}
// We should have a Float32Array
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, array));
3921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990
if (!m_currentProgram
|| !typedArray
|| !locationObj
|| typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array)
return;
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "numMatrices:" << (typedArray->length() / 16);
int uniformLocation = locationObj->id();
float *arrayData = (float *)typedArray->arrayData()->data();
int numMatrices = typedArray->length() / 16;
glUniformMatrix4fv(uniformLocation, numMatrices, transpose, arrayData);
logAllGLErrors(__FUNCTION__);
}
/*!
* \internal
*/
void CanvasContext::uniformMatrix4fva(CanvasUniformLocation *uniformLocation, bool transpose,
QVariantList array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << uniformLocation
<< ", transpose:" << transpose
<< ", array:" << array
<< ")";
if (!m_currentProgram || !uniformLocation)
return;
int location3D = uniformLocation->id();
int size = array.count();
float *arrayData = new float[size];
int numMatrices = size / 16;
ArrayUtils::fillFloatArrayFromVariantList(array, arrayData);
glUniformMatrix4fv(location3D, numMatrices, transpose, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \internal
*/
void CanvasContext::uniformMatrix3fva(CanvasUniformLocation *uniformLocation, bool transpose,
QVariantList array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << uniformLocation
<< ", transpose:" << transpose
<< ", array:" << array
<< ")";
if (!m_currentProgram || !uniformLocation)
return;
int location3D = uniformLocation->id();
int size = array.count();
float *arrayData = new float[size];
int numMatrices = size / 9;
ArrayUtils::fillFloatArrayFromVariantList(array, arrayData);
glUniformMatrix3fv(location3D, numMatrices, transpose, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
3991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060
/*!
* \internal
*/
void CanvasContext::uniformMatrix2fva(CanvasUniformLocation *uniformLocation, bool transpose,
QVariantList array)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(location3D:" << uniformLocation
<< ", transpose:" << transpose
<< ", array:" << array
<< ")";
if (!m_currentProgram || !uniformLocation)
return;
int location3D = uniformLocation->id();
int size = array.count();
float *arrayData = new float[size];
int numMatrices = size / 4;
ArrayUtils::fillFloatArrayFromVariantList(array, arrayData);
glUniformMatrix2fv(location3D, numMatrices, transpose, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \qmlmethod void Context3D::vertexAttribPointer(int indx, int size, glEnums type, bool normalized, int stride, long offset)
* Sets the currently bound array buffer to the vertex attribute at the index passed at \a indx.
* \a size is the number of components per attribute. \a stride specifies the byte offset between
* consecutive vertex attributes. \a offset specifies the byte offset to the first vertex attribute
* in the array. If int values should be normalized, set \a normalized to \c{true}.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttribPointer(int indx, int size, glEnums type,
bool normalized, int stride, long offset)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx:" << indx
<< ", size: " << size
<< ", type:" << glEnumToString(type)
<< ", normalized:" << normalized
<< ", stride:" << stride
<< ", offset:" << offset
<< ")";
glVertexAttribPointer(indx, size, GLenum(type), normalized, stride, (GLvoid *)offset);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::bufferData(glEnums target, long size, glEnums usage)
* Sets the size of the \a target buffer to \a size. Target buffer must be either
* \c{Context3D.ARRAY_BUFFER} or \c{Context3D.ELEMENT_ARRAY_BUFFER}. \a usage sets the usage pattern
* of the data, and must be one of \c{Context3D.STREAM_DRAW}, \c{Context3D.STATIC_DRAW}, or
* \c{Context3D.DYNAMIC_DRAW}.
*/
/*!
* \internal
*/
void CanvasContext::bufferData(glEnums target, long size, glEnums usage)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
4061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130
<< ", size:" << size
<< ", usage:" << glEnumToString(usage)
<< ")";
switch (target) {
case ARRAY_BUFFER:
if (!m_currentArrayBuffer) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION called with no ARRAY_BUFFER bound";
m_error = INVALID_OPERATION;
return;
}
break;
case ELEMENT_ARRAY_BUFFER:
if (!m_currentElementArrayBuffer) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION called with no "
<< "ELEMENT_ARRAY_BUFFER bound";
m_error = INVALID_OPERATION;
return;
}
break;
default:
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM unknown target";
m_error = INVALID_ENUM;
return;
}
glBufferData(GLenum(target), size, (GLvoid *) 0, GLenum(usage));
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::bufferData(glEnums target, value data, glEnums usage)
* Writes the \a data held in \c{ArrayBufferView} or \c{ArrayBuffer} to the \a target buffer.
* Target buffer must be either \c{Context3D.ARRAY_BUFFER } or \c{Context3D.ELEMENT_ARRAY_BUFFER}.
* \a usage sets the usage pattern of the data, and must be one of \c{Context3D.STREAM_DRAW},
* \c{Context3D.STATIC_DRAW}, or \c{Context3D.DYNAMIC_DRAW}.
*/
/*!
* \internal
*/
void CanvasContext::bufferData(glEnums target, QJSValue data, glEnums usage)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", data:" << data.toString()
<< ", usage:" << glEnumToString(usage)
<< ")";
if (data.isNull()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_VALUE called with null data";
m_error = INVALID_VALUE;
return;
}
if (target != ARRAY_BUFFER && target != ELEMENT_ARRAY_BUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM target must be either ARRAY_BUFFER"
<< " or ELEMENT_ARRAY_BUFFER.";
m_error = INVALID_ENUM;
return;
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, data));
4131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200
QV4::Scoped<QV4::ArrayBuffer> arrayBuffer(scope,
QJSValuePrivate::convertedToValue(m_v4engine, data));
if (typedArray) {
glBufferData(GLenum(target),
typedArray->byteLength(),
(GLvoid *) typedArray->arrayData()->data(),
GLenum(usage));
logAllGLErrors(__FUNCTION__);
} else if (arrayBuffer) {
glBufferData(GLenum(target),
arrayBuffer->byteLength(),
(GLvoid *) arrayBuffer->data(),
GLenum(usage));
logAllGLErrors(__FUNCTION__);
} else {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_VALUE data must be either"
<< "TypedArray or ArrayBuffer";
m_error = INVALID_VALUE;
return;
}
}
/*!
* \qmlmethod void Context3D::bufferSubData(glEnums target, int offset, value data)
* Writes the \a data held in \c{ArrayBufferView} or \c{ArrayBuffer} starting from \a offset to the
* \a target buffer. Target buffer must be either \c Context3D.ARRAY_BUFFER or
* \c{Context3D.ELEMENT_ARRAY_BUFFER}.
*/
/*!
* \internal
*/
void CanvasContext::bufferSubData(glEnums target, int offset, QJSValue data)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", offset:"<< offset
<< ", data:" << data.toString()
<< ")";
if (target != ARRAY_BUFFER && target != ELEMENT_ARRAY_BUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM target must be either ARRAY_BUFFER"
<< " or ELEMENT_ARRAY_BUFFER.";
m_error = INVALID_ENUM;
return;
}
if (data.isNull()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": INVALID_VALUE called with null data";
m_error = INVALID_VALUE;
return;
}
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::TypedArray> typedArray(scope,
QJSValuePrivate::convertedToValue(m_v4engine, data));
QV4::Scoped<QV4::ArrayBuffer> arrayBuffer(scope,
QJSValuePrivate::convertedToValue(m_v4engine, data));
if (typedArray) {
glBufferSubData(GLenum(target),
offset,
typedArray->byteLength(),
(GLvoid *) typedArray->arrayData()->data());
logAllGLErrors(__FUNCTION__);
} else if (arrayBuffer) {
glBufferSubData(GLenum(target),
4201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270
offset,
arrayBuffer->byteLength(),
(GLvoid *) arrayBuffer->data());
logAllGLErrors(__FUNCTION__);
} else {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_VALUE data must be either"
<< "TypedArray or ArrayBuffer";
m_error = INVALID_VALUE;
return;
}
}
/*!
* \qmlmethod value Context3D::getBufferParameter(glEnums target, glEnums pname)
* Returns the value for the passed \a pname of the \a target. Target
* must be either \c Context3D.ARRAY_BUFFER or \c{Context3D.ELEMENT_ARRAY_BUFFER}. pname must be
* either \c Context3D.BUFFER_SIZE or \c{Context3D.BUFFER_USAGE}.
*/
/*!
* \internal
*/
QJSValue CanvasContext::getBufferParameter(glEnums target, glEnums pname)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", pname" << glEnumToString(pname)
<< ")";
if (target != ARRAY_BUFFER && target != ELEMENT_ARRAY_BUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM target must be either ARRAY_BUFFER"
<< " or ELEMENT_ARRAY_BUFFER.";
m_error = INVALID_ENUM;
return m_engine->newObject();
}
switch (pname) {
case BUFFER_SIZE:
case BUFFER_USAGE:
GLint data;
glGetBufferParameteriv(GLenum(target), GLenum(pname), &data);
logAllGLErrors(__FUNCTION__);
return QJSValue(data);
default:
break;
}
qCWarning(canvas3drendering) << "getBufferParameter() : UNKNOWN pname";
m_error = INVALID_ENUM;
return m_engine->newObject();
}
/*!
* \qmlmethod bool Context3D::isBuffer(Object anyObject)
* Returns \c true if the given \a anyObect is a valid Buffer3D object and \c false otherwise.
*/
/*!
* \internal
*/
bool CanvasContext::isBuffer(QJSValue anyObject)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(anyObject:" << anyObject.toString()
<< ")";
CanvasBuffer *buffer = getAsBuffer3D(anyObject);
if (!buffer)
return false;
4271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340
return glIsBuffer(buffer->id());
}
/*!
* \internal
*/
CanvasBuffer *CanvasContext::getAsBuffer3D(QJSValue anyObject) const
{
if (!isOfType(anyObject, "QtCanvas3D::CanvasBuffer"))
return 0;
CanvasBuffer *buffer = static_cast<CanvasBuffer *>(anyObject.toQObject());
if (!buffer->isAlive())
return 0;
return buffer;
}
/*!
* \qmlmethod void Context3D::deleteBuffer(Buffer3D buffer3D)
* Deletes the \a buffer3D. Has no effect if the Buffer3D object has been deleted already.
*/
/*!
* \internal
*/
void CanvasContext::deleteBuffer(QJSValue buffer3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(buffer:" << buffer3D.toString()
<< ")";
CanvasBuffer *bufferObj = getAsBuffer3D(buffer3D);
if (!bufferObj) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ": WARNING invalid buffer target" << buffer3D.toString();
return;
}
m_idToCanvasBufferMap.remove(bufferObj->id());
bufferObj->del();
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod glEnums Context3D::getError()
* Returns the error value, if any.
*/
/*!
* \internal
*/
CanvasContext::glEnums CanvasContext::getError()
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__;
glEnums retVal = m_error;
m_error = NO_ERROR;
if (retVal == NO_ERROR)
retVal = glEnums(glGetError());
return retVal;
}
/*!
* \qmlmethod variant Context3D::getParameter(glEnums pname)
* Returns the value for the given \a pname. pname must be one of \c{Context3D.RED_BITS},
* \c{Context3D.GREEN_BITS}, \c{Context3D.BLUE_BITS}, \c{Context3D.ALPHA_BITS},
* \c{Context3D.DEPTH_BITS}, \c{Context3D.STENCIL_BITS}, \c{Context3D.MAX_TEXTURE_IMAGE_UNITS},
* \c{Context3D.MAX_VERTEX_TEXTURE_IMAGE_UNITS}, \c{Context3D.MAX_TEXTURE_SIZE},
* \c{Context3D.MAX_CUBE_MAP_TEXTURE_SIZE}, \c{Context3D.MAX_VERTEX_UNIFORM_VECTORS}
* (not supported in OpenGL ES2), \c{Context3D.RENDERER}, \c{Context3D.SHADING_LANGUAGE_VERSION},
* \c{Context3D.VENDOR}, \c{Context3D.VERSION}, \c{Context3D.UNMASKED_VENDOR_WEBGL}, or
4341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410
* \c{Context3D.UNMASKED_RENDERER_WEBGL}.
*/
/*!
* \internal
*/
QJSValue CanvasContext::getParameter(glEnums pname)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "( pname:" << glEnumToString(pname)
<< ")";
// TODO: Implement these:
// CURRENT_PROGRAM m_currentProgram
// ELEMENT_ARRAY_BUFFER_BINDING m_currentElementArrayBuffer
// FRAMEBUFFER_BINDING WebGLFramebuffer
// RENDERBUFFER_BINDING WebGLRenderbuffer
// ARRAY_BUFFER_BINDING m_currentArrayBuffer
// TEXTURE_BINDING_2D m_currentTexture2D
// TEXTURE_BINDING_CUBE_MAP m_currentTextureCubeMap
switch (pname) {
// GLint values
// Intentional flow through
case MAX_COMBINED_TEXTURE_IMAGE_UNITS:
case MAX_FRAGMENT_UNIFORM_VECTORS:
case MAX_RENDERBUFFER_SIZE:
case MAX_VARYING_VECTORS:
case MAX_VERTEX_ATTRIBS:
case MAX_VERTEX_TEXTURE_IMAGE_UNITS:
#if defined(QT_OPENGL_ES_2)
case MAX_VERTEX_UNIFORM_VECTORS:
#endif
case PACK_ALIGNMENT:
case SAMPLE_BUFFERS:
case SAMPLES:
case STENCIL_BACK_REF:
case STENCIL_CLEAR_VALUE:
case STENCIL_REF:
case SUBPIXEL_BITS:
case UNPACK_ALIGNMENT:
case RED_BITS:
case GREEN_BITS:
case BLUE_BITS:
case ALPHA_BITS:
case DEPTH_BITS:
case STENCIL_BITS:
case MAX_TEXTURE_IMAGE_UNITS:
case MAX_TEXTURE_SIZE:
case MAX_CUBE_MAP_TEXTURE_SIZE:
{
GLint value;
glGetIntegerv(pname, &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(int(value));
}
// GLuint values
// Intentional flow through
case STENCIL_BACK_VALUE_MASK:
case STENCIL_BACK_WRITEMASK:
case STENCIL_VALUE_MASK:
case STENCIL_WRITEMASK:
{
GLint value;
glGetIntegerv(pname, &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(uint(value));
}
case FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
4411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480
if (m_standardDerivatives) {
GLint value;
glGetIntegerv(pname, &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(value);
}
m_error = INVALID_ENUM;
return QJSValue(QJSValue::NullValue);
#if !defined(QT_OPENGL_ES_2)
case MAX_VERTEX_UNIFORM_VECTORS: {
GLint value;
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &value);
logAllGLErrors(__FUNCTION__);
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ << "():" << value;
return QJSValue(value);
}
#endif
// GLboolean values
// Intentional flow through
case BLEND:
case CULL_FACE:
case DEPTH_TEST:
case DEPTH_WRITEMASK:
case DITHER:
case POLYGON_OFFSET_FILL:
case SAMPLE_COVERAGE_INVERT:
case SCISSOR_TEST:
case STENCIL_TEST: {
GLboolean value;
glGetBooleanv(pname, &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(bool(value));
}
case UNPACK_FLIP_Y_WEBGL:
return QJSValue(m_unpackFlipYEnabled);
case UNPACK_PREMULTIPLY_ALPHA_WEBGL:
return QJSValue(m_unpackPremultiplyAlphaEnabled);
// GLenum values
// Intentional flow through
case ACTIVE_TEXTURE:
case BLEND_DST_ALPHA:
case BLEND_DST_RGB:
case BLEND_EQUATION_ALPHA:
case BLEND_EQUATION_RGB:
case BLEND_SRC_ALPHA:
case BLEND_SRC_RGB:
case CULL_FACE_MODE:
case DEPTH_FUNC:
case FRONT_FACE:
case GENERATE_MIPMAP_HINT:
case STENCIL_BACK_FAIL:
case STENCIL_BACK_FUNC:
case STENCIL_BACK_PASS_DEPTH_FAIL:
case STENCIL_BACK_PASS_DEPTH_PASS:
case STENCIL_FAIL:
case STENCIL_FUNC:
case STENCIL_PASS_DEPTH_FAIL:
case STENCIL_PASS_DEPTH_PASS: {
GLint value;
glGetIntegerv(pname, &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(glEnums(value));
}
case IMPLEMENTATION_COLOR_READ_FORMAT:
return QJSValue(QJSValue::UndefinedValue);
case IMPLEMENTATION_COLOR_READ_TYPE:
4481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550
return QJSValue(QJSValue::UndefinedValue);
case UNPACK_COLORSPACE_CONVERSION_WEBGL:
return QJSValue(BROWSER_DEFAULT_WEBGL);
// Float32Array (with 2 elements)
// Intentional flow through
case ALIASED_LINE_WIDTH_RANGE:
case ALIASED_POINT_SIZE_RANGE:
case DEPTH_RANGE: {
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::ArrayBuffer> buffer(scope,
m_v4engine->memoryManager->alloc<QV4::ArrayBuffer>(
m_v4engine,
sizeof(float) * 2));
glGetFloatv(pname, (float *) buffer->data());
logAllGLErrors(__FUNCTION__);
QV4::ScopedFunctionObject constructor(scope,
m_v4engine->typedArrayCtors[
QV4::Heap::TypedArray::Float32Array]);
QV4::ScopedCallData callData(scope, 1);
callData->args[0] = buffer;
return QJSValue(m_v4engine, constructor->construct(callData));
}
// Float32Array (with 4 values)
// Intentional flow through
case BLEND_COLOR:
case COLOR_CLEAR_VALUE: {
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::ArrayBuffer> buffer(scope,
m_v4engine->memoryManager->alloc<QV4::ArrayBuffer>(
m_v4engine,
sizeof(float) * 4));
glGetFloatv(pname, (float *) buffer->data());
logAllGLErrors(__FUNCTION__);
QV4::ScopedFunctionObject constructor(scope,
m_v4engine->typedArrayCtors[
QV4::Heap::TypedArray::Float32Array]);
QV4::ScopedCallData callData(scope, 1);
callData->args[0] = buffer;
return QJSValue(m_v4engine, constructor->construct(callData));
}
// Int32Array (with 2 elements)
case MAX_VIEWPORT_DIMS: {
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::ArrayBuffer> buffer(scope,
m_v4engine->memoryManager->alloc<QV4::ArrayBuffer>(
m_v4engine,
sizeof(int) * 2));
glGetIntegerv(pname, (int *) buffer->data());
logAllGLErrors(__FUNCTION__);
QV4::ScopedFunctionObject constructor(scope,
m_v4engine->typedArrayCtors[
QV4::Heap::TypedArray::Int32Array]);
QV4::ScopedCallData callData(scope, 1);
callData->args[0] = buffer;
return QJSValue(m_v4engine, constructor->construct(callData));
}
break;
// Int32Array (with 4 elements)
// Intentional flow through
case SCISSOR_BOX:
case VIEWPORT: {
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::ArrayBuffer> buffer(scope,
4551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620
m_v4engine->memoryManager->alloc<QV4::ArrayBuffer>(
m_v4engine,
sizeof(int) * 4));
glGetIntegerv(pname, (int *) buffer->data());
logAllGLErrors(__FUNCTION__);
QV4::ScopedFunctionObject constructor(scope,
m_v4engine->typedArrayCtors[
QV4::Heap::TypedArray::Int32Array]);
QV4::ScopedCallData callData(scope, 1);
callData->args[0] = buffer;
return QJSValue(m_v4engine, constructor->construct(callData));
}
// sequence<GLboolean> (with 4 values)
// Intentional flow through
case COLOR_WRITEMASK: {
GLboolean values[4];
glGetBooleanv(COLOR_WRITEMASK, values);
logAllGLErrors(__FUNCTION__);
QJSValue arrayValue = m_engine->newArray(4);
arrayValue.setProperty(0, values[0]);
arrayValue.setProperty(1, values[1]);
arrayValue.setProperty(2, values[2]);
arrayValue.setProperty(3, values[3]);
return arrayValue;
}
// GLfloat values
// Intentional flow through
case DEPTH_CLEAR_VALUE:
case LINE_WIDTH:
case POLYGON_OFFSET_FACTOR:
case POLYGON_OFFSET_UNITS:
case SAMPLE_COVERAGE_VALUE: {
GLfloat value;
glGetFloatv(pname, &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(float(value));
}
// DomString values
// Intentional flow through
case RENDERER:
case SHADING_LANGUAGE_VERSION:
case VENDOR:
case VERSION: {
const GLubyte *text = glGetString(pname);
logAllGLErrors(__FUNCTION__);
QString qtext = QString::fromLatin1((const char *)text);
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ << "():" << qtext;
return QJSValue(qtext);
}
case UNMASKED_VENDOR_WEBGL: {
const GLubyte *text = glGetString(GL_VENDOR);
logAllGLErrors(__FUNCTION__);
QString qtext = QString::fromLatin1((const char *)text);
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ << "():" << qtext;
return QJSValue(qtext);
}
case UNMASKED_RENDERER_WEBGL: {
const GLubyte *text = glGetString(GL_VENDOR);
logAllGLErrors(__FUNCTION__);
QString qtext = QString::fromLatin1((const char *)text);
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ << "():" << qtext;
return QJSValue(qtext);
}
case COMPRESSED_TEXTURE_FORMATS: {
GLint numFormats;
glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats);
4621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690
if (numFormats > 0) {
QV4::Scope scope(m_v4engine);
QV4::Scoped<QV4::ArrayBuffer> buffer(scope,
m_v4engine->memoryManager->alloc<QV4::ArrayBuffer>(
m_v4engine,
sizeof(int) * numFormats));
glGetIntegerv(pname, (int *) buffer->data());
logAllGLErrors(__FUNCTION__);
QV4::ScopedFunctionObject constructor(scope,
m_v4engine->typedArrayCtors[
QV4::Heap::TypedArray::Int32Array]);
QV4::ScopedCallData callData(scope, 1);
callData->args[0] = buffer;
return QJSValue(m_v4engine, constructor->construct(callData));
}
}
default: {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "(): UNIMPLEMENTED PARAMETER NAME" << glEnumToString(pname);
return QJSValue(QJSValue::NullValue);
}
}
return QJSValue(QJSValue::NullValue);
}
/*!
* \qmlmethod string Context3D::getShaderInfoLog(Shader3D shader)
* Returns the info log string of the given \a shader.
*/
/*!
* \internal
*/
QJSValue CanvasContext::getShaderInfoLog(QJSValue shader3D) const
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(shader3D:" << shader3D.toString()
<< ")";
CanvasShader *shader = getAsShader3D(shader3D);
if (!shader) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< "WARNING: invalid shader handle:" << shader3D.toString();
return m_engine->newObject();
}
return QJSValue(shader->qOGLShader()->log());
}
/*!
* \qmlmethod string Context3D::getProgramInfoLog(Program3D program3D)
* Returns the info log string of the given \a program3D.
*/
/*!
* \internal
*/
QString CanvasContext::getProgramInfoLog(QJSValue program3D) const
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ")";
CanvasProgram *program = getAsProgram3D(program3D);
if (!program)
return QString();
return program->log();
}
/*!
4691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760
* \qmlmethod void Context3D::bindBuffer(glEnums target, Buffer3D buffer3D)
* Binds the given \a buffer3D to the given \a target. Target must be either
* \c Context3D.ARRAY_BUFFER or \c{Context3D.ELEMENT_ARRAY_BUFFER}. If the \a buffer3D given is
* \c{null}, the current buffer bound to the target is unbound.
*/
/*!
* \internal
*/
void CanvasContext::bindBuffer(glEnums target, QJSValue buffer3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target:" << glEnumToString(target)
<< ", buffer:" << buffer3D.toString()
<< ")";
if (target != ARRAY_BUFFER && target != ELEMENT_ARRAY_BUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM target must be either ARRAY_BUFFER or"
<< "ELEMENT_ARRAY_BUFFER.";
m_error = INVALID_ENUM;
return;
}
CanvasBuffer *buffer = getAsBuffer3D(buffer3D);
if (buffer) {
if (target == ARRAY_BUFFER) {
if (buffer->target() == CanvasBuffer::UNINITIALIZED)
buffer->setTarget(CanvasBuffer::ARRAY_BUFFER);
if (buffer->target() != CanvasBuffer::ARRAY_BUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION can't rebind "
<< "ELEMENT_ARRAY_BUFFER as ARRAY_BUFFER";
m_error = INVALID_OPERATION;
return;
}
m_currentArrayBuffer = buffer;
} else {
if (buffer->target() == CanvasBuffer::UNINITIALIZED)
buffer->setTarget(CanvasBuffer::ELEMENT_ARRAY_BUFFER);
if (buffer->target() != CanvasBuffer::ELEMENT_ARRAY_BUFFER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION can't rebind "
<< "ARRAY_BUFFER as ELEMENT_ARRAY_BUFFER";
m_error = INVALID_OPERATION;
return;
}
m_currentElementArrayBuffer = buffer;
}
glBindBuffer(GLenum(target), buffer->id());
logAllGLErrors(__FUNCTION__);
} else {
glBindBuffer(GLenum(target), 0);
logAllGLErrors(__FUNCTION__);
}
}
// TODO: Is this function useful? We don't offer a way to query the status.
/*!
* \qmlmethod void Context3D::validateProgram(Program3D program3D)
* Validates the given \a program3D. The validation status is stored into the state of the shader
* program container in \a program3D.
*/
/*!
* \internal
*/
void CanvasContext::validateProgram(QJSValue program3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
4761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830
<< "(program3D:" << program3D.toString() << ")";
CanvasProgram *program = getAsProgram3D(program3D);
if (program)
program->validateProgram();
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::useProgram(Program3D program)
* Installs the given \a program3D as a part of the current rendering state.
*/
/*!
* \internal
*/
void CanvasContext::useProgram(QJSValue program3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString() << ")";
CanvasProgram *program = getAsProgram3D(program3D);
m_currentProgram = program;
if (!program || !program->isLinked())
return;
program->bind();
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::clear(glEnums flags)
* Clears the given \a flags.
*/
/*!
* \internal
*/
void CanvasContext::clear(glEnums flags)
{
if (!((QLoggingCategory &) canvas3drendering()).isDebugEnabled()) {
QString flagStr;
if (flags && COLOR_BUFFER_BIT != 0)
flagStr.append(" COLOR_BUFFER_BIT ");
if (flags && DEPTH_BUFFER_BIT != 0)
flagStr.append(" DEPTH_BUFFER_BIT ");
if (flags && STENCIL_BUFFER_BIT != 0)
flagStr.append(" STENCIL_BUFFER_BIT ");
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(flags:" << flagStr << ")";
}
glClear(flags);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::cullFace(glEnums mode)
* Sets the culling to \a mode. Must be one of \c{Context3D.FRONT}, \c{Context3D.BACK},
* or \c{Context3D.FRONT_AND_BACK}. Defaults to \c{Context3D.BACK}.
*/
/*!
* \internal
*/
void CanvasContext::cullFace(glEnums mode)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(mode:" << glEnumToString(mode) << ")";
glCullFace(mode);
logAllGLErrors(__FUNCTION__);
4831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900
}
/*!
* \qmlmethod void Context3D::frontFace(glEnums mode)
* Sets the front face drawing to \a mode. Must be either \c Context3D.CW
* or \c{Context3D.CCW}. Defaults to \c{Context3D.CCW}.
*/
/*!
* \internal
*/
void CanvasContext::frontFace(glEnums mode)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(mode:" << glEnumToString(mode) << ")";
glFrontFace(mode);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::depthMask(bool flag)
* Enables or disables the depth mask based on \a flag. Defaults to \c{true}.
*/
/*!
* \internal
*/
void CanvasContext::depthMask(bool flag)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(flag:" << flag << ")";
if (flag)
glDepthMask(GL_TRUE);
else
glDepthMask(GL_FALSE);
logAllGLErrors(__FUNCTION__);
}
// TODO: Why are all the enums for this commented out?
/*!
* \qmlmethod void Context3D::depthFunc(glEnums func)
* Sets the depth function to \a func. Must be one of \c{Context3D.NEVER}, \c{Context3D.LESS},
* \c{Context3D.EQUAL}, \c{Context3D.LEQUAL}, \c{Context3D.GREATER}, \c{Context3D.NOTEQUAL},
* \c{Context3D.GEQUAL}, or \c{Context3D.ALWAYS}. Defaults to \c{Context3D.LESS}.
*/
/*!
* \internal
*/
void CanvasContext::depthFunc(glEnums func)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(func:" << glEnumToString(func) << ")";
glDepthFunc(GLenum(func));
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::depthRange(float zNear, float zFar)
* Sets the depth range between \a zNear and \a zFar. Values are clamped to \c{[0, 1]}. \a zNear
* must be less or equal to \a zFar. zNear Range defaults to \c{[0, 1]}.
*/
/*!
* \internal
*/
void CanvasContext::depthRange(float zNear, float zFar)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(zNear:" << zNear
<< ", zFar:" << zFar << ")";
glDepthRangef(GLclampf(zNear), GLclampf(zFar));
logAllGLErrors(__FUNCTION__);
4901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970
}
/*!
* \qmlmethod void Context3D::clearStencil(int stencil)
* Sets the clear value for the stencil buffer to \a stencil. Defaults to \c{0}.
*/
/*!
* \internal
*/
void CanvasContext::clearStencil(int stencil)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(stencil:" << stencil << ")";
glClearStencil(stencil);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::colorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha)
* Enables or disables the writing of colors to the frame buffer based on \a maskRed, \a maskGreen,
* \a maskBlue and \a maskAlpha. All default to \c{true}.
*/
/*!
* \internal
*/
void CanvasContext::colorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(maskRed:" << maskRed
<< ", maskGreen:" << maskGreen
<< ", maskBlue:" << maskBlue
<< ", maskAlpha:" << maskAlpha << ")";
glColorMask(maskRed, maskGreen, maskBlue, maskAlpha);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::clearDepth(float depth)
* Sets the clear value for the depth buffer to \a depth. Must be between \c{[0, 1]}. Defaults
* to \c{1}.
*/
/*!
* \internal
*/
void CanvasContext::clearDepth(float depth)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(depth:" << depth << ")";
glClearDepthf(depth);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::clearColor(float red, float green, float blue, float alpha)
* Sets the clear values for the color buffers with \a red, \a green, \a blue and \a alpha. Values
* must be between \c{[0, 1]}. All default to \c{0}.
*/
/*!
* \internal
*/
void CanvasContext::clearColor(float red, float green, float blue, float alpha)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(red:" << red
<< ", green:" << green
<< ", blue:" << blue
<< ", alpha:" << alpha << ")";
glClearColor(red, green, blue, alpha);
logAllGLErrors(__FUNCTION__);
}
4971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040
/*!
* \qmlmethod Context3D::viewport(int x, int y, int width, int height)
* Defines the affine transformation from normalized x and y device coordinates to window
* coordinates within the drawing buffer.
* \a x defines the left edge of the viewport.
* \a y defines the bottom edge of the viewport.
* \a width defines the width of the viewport.
* \a height defines the height of the viewport.
*/
/*!
* \internal
*/
void CanvasContext::viewport(int x, int y, int width, int height)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(x:" << x
<< ", y:" << y
<< ", width:" << width
<< ", height:" << height << ")";
glViewport(x, y, width, height);
logAllGLErrors(__FUNCTION__);
m_glViewportRect.setX(x);
m_glViewportRect.setY(y);
m_glViewportRect.setWidth(width);
m_glViewportRect.setHeight(height);
}
/*!
* \qmlmethod void Context3D::drawArrays(glEnums mode, int first, int count)
* Renders the geometric primitives held in the currently bound array buffer starting from \a first
* up to \a count using \a mode for drawing. Mode can be one of:
* \list
* \li \c{Context3D.POINTS}
* \li \c{Context3D.LINES}
* \li \c{Context3D.LINE_LOOP}
* \li \c{Context3D.LINE_STRIP}
* \li \c{Context3D.TRIANGLES}
* \li \c{Context3D.TRIANGLE_STRIP}
* \li \c{Context3D.TRIANGLE_FAN}
* \endlist
*/
/*!
* \internal
*/
void CanvasContext::drawArrays(glEnums mode, int first, int count)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(mode:" << glEnumToString(mode)
<< ", first:" << first
<< ", count:" << count << ")";
glDrawArrays(mode, first, count);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::drawElements(glEnums mode, int count, glEnums type, long offset)
* Renders the number of geometric elements given in \a count held in the currently bound element
* array buffer using \a mode for drawing. Mode can be one of:
* \list
* \li \c{Context3D.POINTS}
* \li \c{Context3D.LINES}
* \li \c{Context3D.LINE_LOOP}
* \li \c{Context3D.LINE_STRIP}
* \li \c{Context3D.TRIANGLES}
* \li \c{Context3D.TRIANGLE_STRIP}
* \li \c{Context3D.TRIANGLE_FAN}
* \endlist
*
* \a type specifies the element type and can be one of:
5041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110
* \list
* \li \c Context3D.UNSIGNED_BYTE
* \li \c{Context3D.UNSIGNED_SHORT}
* \endlist
*
* \a offset specifies the location3D where indices are stored.
*/
/*!
* \internal
*/
void CanvasContext::drawElements(glEnums mode, int count, glEnums type, long offset)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(mode:" << glEnumToString(mode)
<< ", count:" << count
<< ", type:" << glEnumToString(type)
<< ", offset:" << offset << ")";
glDrawElements(GLenum(mode), count, GLenum(type), (GLvoid*)offset);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::readPixels(int x, int y, long width, long height, glEnums format, glEnums type, ArrayBufferView pixels)
* Returns the pixel data in the rectangle specified by \a x, \a y, \a width and \a height of the
* frame buffer in \a pixels using \a format (must be \c{Context3D.RGBA}) and \a type
* (must be \c{Context3D.UNSIGNED_BYTE}).
*/
/*!
* \internal
*/
void CanvasContext::readPixels(int x, int y, long width, long height, glEnums format, glEnums type,
QJSValue pixels)
{
if (format != RGBA) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM format must be RGBA.";
m_error = INVALID_ENUM;
return;
}
if (type != UNSIGNED_BYTE) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM type must be UNSIGNED_BYTE.";
m_error = INVALID_ENUM;
return;
}
if (pixels.isNull()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_VALUE pixels was null.";
m_error = INVALID_VALUE;
return;
}
uchar *bufferPtr = getAsUint8ArrayRawPtr(pixels);
if (!bufferPtr) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION pixels must be Uint8Array.";
m_error = INVALID_OPERATION;
return;
}
glReadPixels(x, y, width, height, format, type, bufferPtr);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod ActiveInfo3D Context3D::getActiveAttrib(Program3D program3D, uint index)
* Returns information about the given active attribute variable defined by \a index for the given
* \a program3D.
5111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180
* \sa ActiveInfo3D
*/
/*!
* \internal
*/
CanvasActiveInfo *CanvasContext::getActiveAttrib(QJSValue program3D, uint index)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ", index:" << index << ")";
CanvasProgram *program = getAsProgram3D(program3D);
if (!program)
return 0;
char *name = new char[512];
GLsizei length = 0;
int size = 0;
GLenum type = 0;
glGetActiveAttrib(program->id(), index, 512, &length, &size, &type, name);
logAllGLErrors(__FUNCTION__);
QString strName(name);
delete [] name;
return new CanvasActiveInfo(size, CanvasContext::glEnums(type), strName);
}
/*!
* \qmlmethod ActiveInfo3D Context3D::getActiveUniform(Program3D program3D, uint index)
* Returns information about the given active uniform variable defined by \a index for the given
* \a program3D.
* \sa ActiveInfo3D
*/
/*!
* \internal
*/
CanvasActiveInfo *CanvasContext::getActiveUniform(QJSValue program3D, uint index)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program3D:" << program3D.toString()
<< ", index:" << index << ")";
CanvasProgram *program = getAsProgram3D(program3D);
if (!program)
return 0;
char *name = new char[512];
GLsizei length = 0;
int size = 0;
GLenum type = 0;
glGetActiveUniform(program->id(), index, 512, &length, &size, &type, name);
logAllGLErrors(__FUNCTION__);
QString strName(name);
delete [] name;
return new CanvasActiveInfo(size, CanvasContext::glEnums(type), strName);
}
/*!
* \qmlmethod void Context3D::stencilFunc(glEnums func, int ref, uint mask)
* Sets front and back function \a func and reference value \a ref for stencil testing.
* Also sets the \a mask value that is ANDed with both reference and stored stencil value when
* the test is done. \a func is initially set to \c{Context3D.ALWAYS} and can be one of:
* \list
* \li \c{Context3D.NEVER}
* \li \c{Context3D.LESS}
* \li \c{Context3D.LEQUAL}
* \li \c{Context3D.GREATER}
* \li \c{Context3D.GEQUAL}
* \li \c{Context3D.EQUAL}
* \li \c{Context3D.NOTEQUAL}
* \li \c{Context3D.ALWAYS}
5181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250
* \endlist
*/
/*!
* \internal
*/
void CanvasContext::stencilFunc(glEnums func, int ref, uint mask)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(func:" << glEnumToString(func)
<< ", ref:" << ref
<< ", mask:" << mask
<< ")";
glStencilFunc(GLenum(func), ref, mask);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::stencilFuncSeparate(glEnums face, glEnums func, int ref, uint mask)
* Sets front and/or back (defined by \a face) function \a func and reference value \a ref for
* stencil testing. Also sets the \a mask value that is ANDed with both reference and stored stencil
* value when the test is done. \a face can be one of:
* \list
* \li \c{Context3D.FRONT}
* \li \c{Context3D.BACK}
* \li \c{Context3D.FRONT_AND_BACK}
* \endlist
* \a func is initially set to \c{Context3D.ALWAYS} and can be one of:
* \list
* \li \c{Context3D.NEVER}
* \li \c{Context3D.LESS}
* \li \c{Context3D.LEQUAL}
* \li \c{Context3D.GREATER}
* \li \c{Context3D.GEQUAL}
* \li \c{Context3D.EQUAL}
* \li \c{Context3D.NOTEQUAL}
* \li \c{Context3D.ALWAYS}
* \endlist
*/
/*!
* \internal
*/
void CanvasContext::stencilFuncSeparate(glEnums face, glEnums func, int ref, uint mask)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(face:" << glEnumToString(face)
<< ", func:" << glEnumToString(func)
<< ", ref:" << ref
<< ", mask:" << mask
<< ")";
glStencilFuncSeparate(GLenum(face), GLenum(func), ref, mask);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::stencilMask(uint mask)
* Controls the front and back writing of individual bits in the stencil planes. \a mask defines
* the bit mask to enable and disable writing of individual bits in the stencil planes.
*/
/*!
* \internal
*/
void CanvasContext::stencilMask(uint mask)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(mask:" << mask
<< ")";
glStencilMask(mask);
logAllGLErrors(__FUNCTION__);
}
5251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320
/*!
* \qmlmethod void Context3D::stencilMaskSeparate(glEnums face, uint mask)
* Controls the front and/or back writing (defined by \a face) of individual bits in the stencil
* planes. \a mask defines the bit mask to enable and disable writing of individual bits in the
* stencil planes. \a face can be one of:
* \list
* \li \c{Context3D.FRONT}
* \li \c{Context3D.BACK}
* \li \c{Context3D.FRONT_AND_BACK}
* \endlist
*/
/*!
* \internal
*/
void CanvasContext::stencilMaskSeparate(glEnums face, uint mask)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(face:" << glEnumToString(face)
<< ", mask:" << mask
<< ")";
glStencilMaskSeparate(GLenum(face), mask);
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::stencilOp(glEnums sfail, glEnums zfail, glEnums zpass)
* Sets the front and back stencil test actions for failing the test \a zfail and passing the test
* \a zpass. \a sfail, \a zfail and \a zpass are initially set to \c{Context3D.KEEP} and can be one
* of:
* \list
* \li \c{Context3D.KEEP}
* \li \c{Context3D.ZERO}
* \li \c{Context3D.GL_REPLACE}
* \li \c{Context3D.GL_INCR}
* \li \c{Context3D.GL_INCR_WRAP}
* \li \c{Context3D.GL_DECR}
* \li \c{Context3D.GL_DECR_WRAP}
* \li \c{Context3D.GL_INVERT}
* \endlist
*/
/*!
* \internal
*/
void CanvasContext::stencilOp(glEnums sfail, glEnums zfail, glEnums zpass)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(sfail:" << glEnumToString(sfail)
<< ", zfail:" << glEnumToString(zfail)
<< ", zpass:" << glEnumToString(zpass)
<< ")";
glStencilOp(GLenum(sfail), GLenum(zfail), GLenum(zpass));
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::stencilOpSeparate(glEnums face, glEnums fail, glEnums zfail, glEnums zpass)
* Sets the front and/or back (defined by \a face) stencil test actions for failing the test
* \a zfail and passing the test \a zpass. \a face can be one of:
* \list
* \li \c{Context3D.FRONT}
* \li \c{Context3D.BACK}
* \li \c{Context3D.FRONT_AND_BACK}
* \endlist
*
* \a sfail, \a zfail and \a zpass are initially set to \c{Context3D.KEEP} and can be one of:
* \list
* \li \c{Context3D.KEEP}
* \li \c{Context3D.ZERO}
* \li \c{Context3D.GL_REPLACE}
5321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390
* \li \c{Context3D.GL_INCR}
* \li \c{Context3D.GL_INCR_WRAP}
* \li \c{Context3D.GL_DECR}
* \li \c{Context3D.GL_DECR_WRAP}
* \li \c{Context3D.GL_INVERT}
* \endlist
*/
/*!
* \internal
*/
void CanvasContext::stencilOpSeparate(glEnums face, glEnums fail, glEnums zfail, glEnums zpass)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(face:" << glEnumToString(face)
<< ", fail:" << glEnumToString(fail)
<< ", zfail:" << glEnumToString(zfail)
<< ", zpass:" << glEnumToString(zpass)
<< ")";
glStencilOpSeparate(GLenum(face), GLenum(fail), GLenum(zfail), GLenum(zpass));
logAllGLErrors(__FUNCTION__);
}
/*!
* \qmlmethod void Context3D::vertexAttrib1fva(int indx, list<variant> values)
* Sets the array of float values given in \a values to the generic vertex attribute index
* specified by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib1fva(uint indx, QVariantList values)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx" << indx
<< ", values:" << values
<< ")";
if (!m_currentProgram)
return;
int size = values.count();
float *arrayData = new float[size];
ArrayUtils::fillFloatArrayFromVariantList(values, arrayData);
glVertexAttrib1fv(indx, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \qmlmethod void Context3D::vertexAttrib2fva(int indx, list<variant> values)
* Sets the array of float values given in \a values to the generic vertex attribute index
* specified by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib2fva(uint indx, QVariantList values)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx" << indx
<< ", values:" << values
<< ")";
if (!m_currentProgram)
return;
int size = values.count();
float *arrayData = new float[size];
5391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460
ArrayUtils::fillFloatArrayFromVariantList(values, arrayData);
glVertexAttrib2fv(indx, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \qmlmethod void Context3D::vertexAttrib3fva(int indx, list<variant> values)
* Sets the array of float values given in \a values to the generic vertex attribute index
* specified by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib3fva(uint indx, QVariantList values)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx" << indx
<< ", values:" << values
<< ")";
if (!m_currentProgram)
return;
int size = values.count();
float *arrayData = new float[size];
ArrayUtils::fillFloatArrayFromVariantList(values, arrayData);
glVertexAttrib3fv(indx, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \qmlmethod void Context3D::vertexAttrib4fva(int indx, list<variant> values)
* Sets the array of float values given in \a values to the generic vertex attribute index
* specified by \a indx.
*/
/*!
* \internal
*/
void CanvasContext::vertexAttrib4fva(uint indx, QVariantList values)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(indx" << indx
<< ", values:" << values
<< ")";
if (!m_currentProgram)
return;
int size = values.count();
float *arrayData = new float[size];
ArrayUtils::fillFloatArrayFromVariantList(values, arrayData);
glVertexAttrib4fv(indx, arrayData);
logAllGLErrors(__FUNCTION__);
delete [] arrayData;
}
/*!
* \qmlmethod int Context3D::getFramebufferAttachmentParameter(glEnums target, glEnums attachment, glEnums pname)
* Returns information specified by \a pname about given \a attachment of a framebuffer object
* bound to the given \a target.
*/
5461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530
/*!
* \internal
*/
int CanvasContext::getFramebufferAttachmentParameter(glEnums target, glEnums attachment,
glEnums pname)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target" << glEnumToString(target)
<< ", attachment:" << glEnumToString(attachment)
<< ", pname:" << glEnumToString(pname)
<< ")";
GLint parameter;
glGetFramebufferAttachmentParameteriv(target, attachment, pname, ¶meter);
logAllGLErrors(__FUNCTION__);
return parameter;
}
/*!
* \qmlmethod int Context3D::getRenderbufferParameter(glEnums target, glEnums pname)
* Returns information specified by \a pname of a renderbuffer object
* bound to the given \a target.
*/
/*!
* \internal
*/
int CanvasContext::getRenderbufferParameter(glEnums target, glEnums pname)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target" << glEnumToString(target)
<< ", pname:" << glEnumToString(pname)
<< ")";
GLint parameter;
glGetRenderbufferParameteriv(target, pname, ¶meter);
logAllGLErrors(__FUNCTION__);
return parameter;
}
/*!
* \qmlmethod variant Context3D::getTexParameter(glEnums target, glEnums pname)
* Returns parameter specified by the \a pname of a texture object
* bound to the given \a target. \a pname must be one of:
* \list
* \li \c{Context3D.TEXTURE_MAG_FILTER}
* \li \c{Context3D.TEXTURE_MIN_FILTER}
* \li \c{Context3D.TEXTURE_WRAP_S}
* \li \c{Context3D.TEXTURE_WRAP_T}
* \endlist
*/
/*!
* \internal
*/
QVariant CanvasContext::getTexParameter(glEnums target, glEnums pname)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(target" << glEnumToString(target)
<< ", pname:" << glEnumToString(pname)
<< ")";
GLint parameter = 0;
if (!m_currentTexture2D) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No current texture bound";
m_error = INVALID_OPERATION;
} else if (!m_currentTexture2D->isAlive()) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION Currently bound texture is deleted";
m_error = INVALID_OPERATION;
} else {
switch (pname) {
5531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600
case TEXTURE_MAG_FILTER:
// Intentional flow through
case TEXTURE_MIN_FILTER:
// Intentional flow through
case TEXTURE_WRAP_S:
// Intentional flow through
case TEXTURE_WRAP_T:
glGetTexParameteriv(target, pname, ¶meter);
logAllGLErrors(__FUNCTION__);
break;
default:
// Intentional flow through
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM invalid pname "<< glEnumToString(pname)
<< " must be one of: TEXTURE_MAG_FILTER, "
<< "TEXTURE_MIN_FILTER, TEXTURE_WRAP_S or TEXTURE_WRAP_T";
m_error = INVALID_ENUM;
break;
}
}
return QVariant::fromValue(parameter);
}
/*!
* \qmlmethod int Context3D::getVertexAttribOffset(int index, glEnums pname)
* Returns the offset of the specified generic vertex attribute pointer \a index. \a pname must be
* \c{Context3D.VERTEX_ATTRIB_ARRAY_POINTER}
* \list
* \li \c{Context3D.TEXTURE_MAG_FILTER}
* \li \c{Context3D.TEXTURE_MIN_FILTER}
* \li \c{Context3D.TEXTURE_WRAP_S}
* \li \c{Context3D.TEXTURE_WRAP_T}
* \endlist
*/
/*!
* \internal
*/
uint CanvasContext::getVertexAttribOffset(uint index, glEnums pname)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(index" << index
<< ", pname:" << glEnumToString(pname)
<< ")";
uint offset = 0;
if (pname != VERTEX_ATTRIB_ARRAY_POINTER) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM pname must be "
<< "VERTEX_ATTRIB_ARRAY_POINTER";
m_error = INVALID_ENUM;
return 0;
}
if (index >= m_maxVertexAttribs) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_VALUE index must be smaller than "
<< m_maxVertexAttribs;
m_error = INVALID_VALUE;
return 0;
}
glGetVertexAttribPointerv(index, GLenum(pname), (GLvoid**) &offset);
logAllGLErrors(__FUNCTION__);
return offset;
}
/*!
* \qmlmethod variant Context3D::getVertexAttrib(int index, glEnums pname)
5601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670
* Returns the requested parameter \a pname of the specified generic vertex attribute pointer
* \a index. The type returned is dependent on the requested \a pname, as shown in the table:
* \table
* \header
* \li pname
* \li Returned Type
* \row
* \li \c{Context3D.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING}
* \li \c{CanvasBuffer}
* \row
* \li \c{Context3D.VERTEX_ATTRIB_ARRAY_ENABLED}
* \li \c{boolean}
* \row
* \li \c{Context3D.VERTEX_ATTRIB_ARRAY_SIZE}
* \li \c{int}
* \row
* \li \c{Context3D.VERTEX_ATTRIB_ARRAY_STRIDE}
* \li \c{int}
* \row
* \li \c{Context3D.VERTEX_ATTRIB_ARRAY_TYPE}
* \li \c{glEnums}
* \row
* \li \c{Context3D.VERTEX_ATTRIB_ARRAY_NORMALIZED}
* \li \c{boolean}
* \row
* \li \c{Context3D.CURRENT_VERTEX_ATTRIB}
* \li \c{sequence<float>} (with 4 elements)
* \endtable
*/
/*!
* \internal
*/
QJSValue CanvasContext::getVertexAttrib(uint index, glEnums pname)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(index" << index
<< ", pname:" << glEnumToString(pname)
<< ")";
if (index >= MAX_VERTEX_ATTRIBS) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_VALUE index must be smaller than "
<< "MAX_VERTEX_ATTRIBS = " << MAX_VERTEX_ATTRIBS;
m_error = INVALID_VALUE;
} else {
switch (pname) {
case VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
GLint value = 0;
glGetVertexAttribiv(index, GLenum(pname), &value);
logAllGLErrors(__FUNCTION__);
if (value == 0 || !m_idToCanvasBufferMap.contains(value))
return m_engine->newObject();
return m_engine->newQObject(m_idToCanvasBufferMap[value]);
}
break;
case VERTEX_ATTRIB_ARRAY_ENABLED: {
GLint value = 0;
glGetVertexAttribiv(index, GLenum(pname), &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(bool(value));
}
break;
case VERTEX_ATTRIB_ARRAY_SIZE: {
GLint value = 0;
glGetVertexAttribiv(index, GLenum(pname), &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(value);
}
break;
5671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740
case VERTEX_ATTRIB_ARRAY_STRIDE: {
GLint value = 0;
glGetVertexAttribiv(index, GLenum(pname), &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(value);
}
break;
case VERTEX_ATTRIB_ARRAY_TYPE: {
GLint value = 0;
glGetVertexAttribiv(index, GLenum(pname), &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(value);
}
case VERTEX_ATTRIB_ARRAY_NORMALIZED: {
GLint value = 0;
glGetVertexAttribiv(index, GLenum(pname), &value);
logAllGLErrors(__FUNCTION__);
return QJSValue(bool(value));
}
case CURRENT_VERTEX_ATTRIB: {
// TODO: Should be Float32Array
GLfloat values[4];
glGetVertexAttribfv(index, GLenum(pname), values);
logAllGLErrors(__FUNCTION__);
QJSValue array = m_engine->newArray(4);
array.setProperty(0, values[0]);
array.setProperty(1, values[1]);
array.setProperty(2, values[2]);
array.setProperty(3, values[3]);
return array;
}
default:
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_ENUM pname " << pname;
m_error = INVALID_ENUM;
}
}
return m_engine->newObject();
}
/*!
* \qmlmethod variant Context3D::getUniform(Program3D program, UniformLocation3D location3D)
* Returns the uniform value at the given \a location3D in the \a program.
* The type returned is dependent on the uniform type, as shown in the table:
* \table
* \header
* \li Data Type
* \li Returned Type
* \row
* \li boolean
* \li sequence<boolean> (with 1 element)
* \row
* \li int
* \li sequence<int> (with 1 element)
* \row
* \li float
* \li sequence<float> (with 1 element)
* \row
* \li vec2
* \li sequence<float> (with 2 elements)
* \row
* \li vec3
* \li sequence<float> (with 3 elements)
* \row
* \li vec4
* \li sequence<float> (with 4 elements)
* \row
* \li ivec2
5741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810
* \li sequence<int> (with 2 elements)
* \row
* \li ivec3
* \li sequence<int> (with 3 elements)
* \row
* \li ivec4
* \li sequence<int> (with 4 elements)
* \row
* \li bvec2
* \li sequence<boolean> (with 2 elements)
* \row
* \li bvec3
* \li sequence<boolean> (with 3 elements)
* \row
* \li bvec4
* \li sequence<boolean> (with 4 elements)
* \row
* \li mat2
* \li sequence<float> (with 4 elements)
* \row
* \li mat3
* \li sequence<float> (with 9 elements)
* \row
* \li mat4
* \li sequence<float> (with 16 elements)
* \row
* \li sampler2D
* \li sequence<int> (with 1 element)
* \row
* \li samplerCube
* \li sequence<int> (with 1 element)
* \endtable
*/
/*!
* \internal
*/
QVariant CanvasContext::getUniform(QJSValue program3D, QJSValue location3D)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(program" << program3D.toString()
<< ", location3D:" << location3D.toString()
<< ")";
CanvasProgram *program = getAsProgram3D(program3D);
CanvasUniformLocation *location = getAsUniformLocation3D(location3D);
if (!program) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No program was specified";
m_error = INVALID_OPERATION;
} else if (!location) {
qCWarning(canvas3drendering) << "Context3D::" << __FUNCTION__
<< ":INVALID_OPERATION No location3D was specified";
m_error = INVALID_OPERATION;
} else {
uint programId = program->id();
uint locationId = location->id();
CanvasActiveInfo *info = getActiveUniform(program3D, locationId);
int numValues = 4;
switch (info->type()) {
case SAMPLER_2D:
// Intentional flow through
case SAMPLER_CUBE:
// Intentional flow through
case INT: {
GLint value = 0;
glGetUniformiv(programId, locationId, &value);
logAllGLErrors(__FUNCTION__);
return QVariant::fromValue(value);
5811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880
}
case INT_VEC2:
numValues--;
// Intentional flow through
case INT_VEC3:
numValues--;
// Intentional flow through
case INT_VEC4: {
numValues--;
GLint *value = new GLint[numValues];
glGetUniformiv(programId, locationId, value);
logAllGLErrors(__FUNCTION__);
QList<float> intList;
for (int i = 0; i < numValues; i++)
intList << value[i];
// TODO: Should return Int32Array
return QVariant::fromValue(intList);
}
case FLOAT: {
GLfloat value = 0;
glGetUniformfv(programId, locationId, &value);
logAllGLErrors(__FUNCTION__);
return QVariant::fromValue(value);
}
case FLOAT_VEC2:
numValues--;
// Intentional flow through
case FLOAT_VEC3:
numValues--;
// Intentional flow through
case FLOAT_VEC4: {
numValues--;
GLfloat *value = new GLfloat[numValues];
glGetUniformfv(programId, locationId, value);
logAllGLErrors(__FUNCTION__);
QList<float> floatList;
for (int i = 0; i < numValues; i++)
floatList << value[i];
// TODO: Should return Float32Array
return QVariant::fromValue(floatList);
}
case BOOL: {
GLint value = 0;
glGetUniformiv(programId, locationId, &value);
logAllGLErrors(__FUNCTION__);
return QVariant::fromValue(bool(value));
}
case BOOL_VEC2:
numValues--;
// Intentional flow through
case BOOL_VEC3:
numValues--;
// Intentional flow through
case BOOL_VEC4: {
numValues--;
GLint *value = new GLint[numValues];
glGetUniformiv(programId, locationId, value);
logAllGLErrors(__FUNCTION__);
QList<bool> boolList;
for (int i = 0; i < numValues; i++)
boolList << value[i];
return QVariant::fromValue(boolList);
5881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950
}
case FLOAT_MAT2:
numValues--;
// Intentional flow through
case FLOAT_MAT3:
numValues--;
// Intentional flow through
case FLOAT_MAT4: {
numValues = numValues * numValues;
GLfloat *value = new GLfloat[numValues];
glGetUniformfv(programId, locationId, value);
logAllGLErrors(__FUNCTION__);
QList<float> floatList;
for (int i = 0; i < numValues; i++)
floatList << value[i];
// TODO: Should return Float32Array
return QVariant::fromValue(floatList);
}
default:
break;
}
}
return QVariant();
}
/*!
* \qmlmethod list<variant> Context3D::getSupportedExtensions()
* Returns an array of the extension strings supported by this implementation
*/
/*!
* \internal
*/
QVariantList CanvasContext::getSupportedExtensions()
{
qCDebug(canvas3drendering).nospace() << Q_FUNC_INFO;
QVariantList list;
list.append(QVariant::fromValue(QStringLiteral("QTCANVAS3D_gl_state_dump")));
if (!m_isOpenGLES2 ||
(m_context->format().majorVersion() >= 3
|| m_extensions.contains("OES_standard_derivatives"))) {
list.append(QVariant::fromValue(QStringLiteral("OES_standard_derivatives")));
}
return list;
}
/*!
* \internal
*/
bool CanvasContext::isOfType(const QJSValue &value, const QString &classname) const
{
if (!value.isQObject()) {
return false;
}
QObject *obj = value.toQObject();
if (!obj)
return false;
if (!obj->inherits(classname.toLocal8Bit().constData())) {
return false;
}
5951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987
return true;
}
/*!
* \qmlmethod variant Context3D::getExtension(string name)
* \return object if given \a name matches a supported extension.
* Otherwise returns \c{null}. The returned object may contain constants and/or functions provided
* by the extension, but at minimum a unique object is returned.
* Case-insensitive \a name of the extension to be returned.
*/
/*!
* \internal
*/
QVariant CanvasContext::getExtension(const QString &name)
{
qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
<< "(name:" << name
<< ")";
QString upperCaseName = name.toUpper();
if (upperCaseName == QStringLiteral("QTCANVAS3D_GL_STATE_DUMP")) {
if (!m_stateDumpExt)
m_stateDumpExt = new CanvasGLStateDump(m_context, this);
return QVariant::fromValue(m_stateDumpExt);
} else if (upperCaseName == QStringLiteral("OES_STANDARD_DERIVATIVES")) {
if (!m_standardDerivatives)
m_standardDerivatives = new QObject(this);
return QVariant::fromValue(m_standardDerivatives);
}
return QVariant(QVariant::Int);
}
QT_CANVAS3D_END_NAMESPACE
QT_END_NAMESPACE