bool WebGraphicsContext3DDefaultImpl::getActiveAttrib(WebGLId program, unsigned long index, ActiveInfo& info) { if (!program) { synthesizeGLError(GL_INVALID_VALUE); return false; } GLint maxNameLength = -1; glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength); if (maxNameLength < 0) return false; GLchar* name = 0; if (!tryFastMalloc(maxNameLength * sizeof(GLchar)).getValue(name)) { synthesizeGLError(GL_OUT_OF_MEMORY); return false; } GLsizei length = 0; GLint size = -1; GLenum type = 0; glGetActiveAttrib(program, index, maxNameLength, &length, &size, &type, name); if (size < 0) { fastFree(name); return false; } info.name = WebString::fromUTF8(name, length); info.type = type; info.size = size; fastFree(name); return true; }
bool GraphicsContext3DPrivate::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) { if (!program) { synthesizeGLError(GL_INVALID_VALUE); return false; } makeContextCurrent(); GLint maxNameLength = 0; m_api->glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); if (!maxNameLength) return false; OwnArrayPtr<char> name = adoptArrayPtr(new char[maxNameLength]); if (!name) { synthesizeGLError(GL_OUT_OF_MEMORY); return false; } GLsizei length = 0; GLint size = 0; GLenum type = 0; m_api->glGetActiveUniform(program, index, maxNameLength, &length, &size, &type, name.get()); if (!length) return false; info.name = String::fromUTF8(name.get(), length); info.type = type; info.size = size; return true; }
bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) { if (!program) { synthesizeGLError(INVALID_VALUE); return false; } makeContextCurrent(); GLint maxLength = 0; glGetProgramiv(static_cast<GLuint>(program), GraphicsContext3D::ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); GLchar* name = (GLchar*) fastMalloc(maxLength); GLsizei nameLength = 0; GLint size = 0; GLenum type = 0; glGetActiveUniform(static_cast<GLuint>(program), index, maxLength, &nameLength, &size, &type, name); if (!nameLength) { fastFree(name); return false; } info.name = String(name, nameLength); info.type = type; info.size = size; fastFree(name); return true; }
bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) { if (width && height && !pixels) { synthesizeGLError(INVALID_VALUE); return false; } GC3Denum openGLInternalFormat = internalformat; if (!isGLES2Compliant()) { if (type == GL_FLOAT) { if (format == GL_RGBA) openGLInternalFormat = GL_RGBA32F; else if (format == GL_RGB) openGLInternalFormat = GL_RGB32F; } else if (type == GL_HALF_FLOAT_OES) { if (format == GL_RGBA) openGLInternalFormat = GL_RGBA16F; else if (format == GL_RGB) openGLInternalFormat = GL_RGB16F; else if (format == GL_LUMINANCE) openGLInternalFormat = GL_LUMINANCE16F_ARB; else if (format == GL_ALPHA) openGLInternalFormat = GL_ALPHA16F_ARB; else if (format == GL_LUMINANCE_ALPHA) openGLInternalFormat = GL_LUMINANCE_ALPHA16F_ARB; type = GL_HALF_FLOAT; } } texImage2DDirect(target, level, openGLInternalFormat, width, height, border, format, type, pixels); return true; }
bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) { if (!program) { synthesizeGLError(INVALID_VALUE); return false; } makeContextCurrent(); GLint maxUniformSize = 0; ::glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize); OwnArrayPtr<GLchar> name = adoptArrayPtr(new GLchar[maxUniformSize]); // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination. GLsizei nameLength = 0; GLint size = 0; GLenum type = 0; ::glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name.get()); if (!nameLength) return false; info.name = String(name.get(), nameLength); info.type = type; info.size = size; return true; }
void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value) { ASSERT(shader); makeContextCurrent(); HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); switch (pname) { case DELETE_STATUS: case SHADER_TYPE: ::glGetShaderiv(shader, pname, value); break; case COMPILE_STATUS: if (result == m_shaderSourceMap.end()) { *value = static_cast<int>(false); return; } *value = static_cast<int>(result->second.isValid); break; case INFO_LOG_LENGTH: if (result == m_shaderSourceMap.end()) { *value = 0; return; } *value = getShaderInfoLog(shader).length(); break; case SHADER_SOURCE_LENGTH: *value = getShaderSource(shader).length(); break; default: synthesizeGLError(INVALID_ENUM); } }
void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders) { if (!program) { synthesizeGLError(INVALID_VALUE); return; } makeContextCurrent(); ::glGetAttachedShaders(program, maxCount, count, shaders); }
bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) { if (width && height && !pixels) { synthesizeGLError(INVALID_VALUE); return false; } texImage2DDirect(target, level, internalformat, width, height, border, format, type, pixels); return true; }
bool GraphicsContext3D::texImage2DResourceSafe(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, GC3Dint unpackAlignment) { ASSERT(unpackAlignment == 1 || unpackAlignment == 2 || unpackAlignment == 4 || unpackAlignment == 8); std::unique_ptr<unsigned char[]> zero; if (!isResourceSafe() && width > 0 && height > 0) { unsigned int size; GC3Denum error = computeImageSizeInBytes(format, type, width, height, unpackAlignment, &size, 0); if (error != GraphicsContext3D::NO_ERROR) { synthesizeGLError(error); return false; } zero = std::make_unique<unsigned char[]>(size); if (!zero) { synthesizeGLError(GraphicsContext3D::INVALID_VALUE); return false; } memset(zero.get(), 0, size); } return texImage2D(target, level, internalformat, width, height, border, format, type, zero.get()); }
void GraphicsContext3D::readPixelsIMG(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) { // Currently only format=RGBA, type=UNSIGNED_BYTE is supported by the specification: http://www.khronos.org/registry/webgl/specs/latest/ // If this ever changes, this code will need to be updated. // Calculate the strides of our data and canvas unsigned formatSize = 4; // RGBA UNSIGNED_BYTE unsigned dataStride = width * formatSize; unsigned canvasStride = m_currentWidth * formatSize; // If we are using a pack alignment of 8, then we need to align our strides to 8 byte boundaries // See: http://en.wikipedia.org/wiki/Data_structure_alignment (computing padding) int packAlignment; glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); if (8 == packAlignment) { dataStride = (dataStride + 7) & ~7; canvasStride = (canvasStride + 7) & ~7; } unsigned char* canvasData = new unsigned char[canvasStride * m_currentHeight]; ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, format, type, canvasData); // If we failed to read our canvas data due to a GL error, don't continue int error = glGetError(); if (GL_NO_ERROR != error) { synthesizeGLError(error); return; } // Clear our data in case some of it lies outside the bounds of our canvas // TODO: don't do this if all of the data lies inside the bounds of the canvas memset(data, 0, dataStride * height); // Calculate the intersection of our canvas and data bounds IntRect dataRect(x, y, width, height); IntRect canvasRect(0, 0, m_currentWidth, m_currentHeight); IntRect nonZeroDataRect = intersection(dataRect, canvasRect); unsigned xDataOffset = x < 0 ? -x * formatSize : 0; unsigned yDataOffset = y < 0 ? -y * dataStride : 0; unsigned xCanvasOffset = nonZeroDataRect.x() * formatSize; unsigned yCanvasOffset = nonZeroDataRect.y() * canvasStride; unsigned char* dst = static_cast<unsigned char*>(data) + xDataOffset + yDataOffset; unsigned char* src = canvasData + xCanvasOffset + yCanvasOffset; for (int row = 0; row < nonZeroDataRect.height(); row++) { memcpy(dst, src, nonZeroDataRect.width() * formatSize); dst += dataStride; src += canvasStride; } delete [] canvasData; }
bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) { if (width && height && !pixels) { synthesizeGLError(INVALID_VALUE); return false; } makeContextCurrent(); GC3Denum openGLInternalFormat = internalformat; if (type == GL_FLOAT) { if (format == GL_RGBA) openGLInternalFormat = GL_RGBA32F_ARB; else if (format == GL_RGB) openGLInternalFormat = GL_RGB32F_ARB; } ::glTexImage2D(target, level, openGLInternalFormat, width, height, border, format, type, pixels); return true; }
bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info) { if (!program) { synthesizeGLError(INVALID_VALUE); return false; } makeContextCurrent(); GLint maxAttributeSize = 0; ::glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize); GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination GLsizei nameLength = 0; GLint size = 0; GLenum type = 0; ::glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name); if (!nameLength) return false; info.name = String(name, nameLength); info.type = type; info.size = size; return true; }
bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) { if (width && height && !pixels) { synthesizeGLError(INVALID_VALUE); return false; } GC3Denum openGLFormat = format; GC3Denum openGLInternalFormat = internalformat; #if !PLATFORM(IOS) if (type == GL_FLOAT) { if (format == GL_RGBA) openGLInternalFormat = GL_RGBA32F_ARB; else if (format == GL_RGB) openGLInternalFormat = GL_RGB32F_ARB; } else if (type == HALF_FLOAT_OES) { if (format == GL_RGBA) openGLInternalFormat = GL_RGBA16F_ARB; else if (format == GL_RGB) openGLInternalFormat = GL_RGB16F_ARB; else if (format == GL_LUMINANCE) openGLInternalFormat = GL_LUMINANCE16F_ARB; else if (format == GL_ALPHA) openGLInternalFormat = GL_ALPHA16F_ARB; else if (format == GL_LUMINANCE_ALPHA) openGLInternalFormat = GL_LUMINANCE_ALPHA16F_ARB; type = GL_HALF_FLOAT_ARB; } ASSERT(format != Extensions3D::SRGB8_ALPHA8_EXT); if (format == Extensions3D::SRGB_ALPHA_EXT) openGLFormat = GL_RGBA; else if (format == Extensions3D::SRGB_EXT) openGLFormat = GL_RGB; #endif texImage2DDirect(target, level, openGLInternalFormat, width, height, border, openGLFormat, type, pixels); return true; }