summaryrefslogtreecommitdiffstats
path: root/WebCore/html/canvas
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/html/canvas')
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.cpp78
-rw-r--r--WebCore/html/canvas/CanvasRenderingContext2D.h2
-rw-r--r--WebCore/html/canvas/CanvasStyle.cpp24
-rw-r--r--WebCore/html/canvas/CanvasStyle.h2
-rw-r--r--WebCore/html/canvas/Float32Array.idl3
-rw-r--r--WebCore/html/canvas/Int16Array.idl3
-rw-r--r--WebCore/html/canvas/Int32Array.idl3
-rw-r--r--WebCore/html/canvas/Int8Array.idl3
-rw-r--r--WebCore/html/canvas/Uint16Array.idl3
-rw-r--r--WebCore/html/canvas/Uint32Array.idl3
-rw-r--r--WebCore/html/canvas/Uint8Array.idl3
-rw-r--r--WebCore/html/canvas/WebGLBuffer.cpp62
-rw-r--r--WebCore/html/canvas/WebGLBuffer.h2
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.cpp184
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.h17
-rw-r--r--WebCore/html/canvas/WebGLRenderingContext.idl6
-rw-r--r--WebCore/html/canvas/WebGLTexture.cpp212
-rw-r--r--WebCore/html/canvas/WebGLTexture.h57
18 files changed, 503 insertions, 164 deletions
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index b3d212a..acd15d2 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -172,6 +172,9 @@ void CanvasRenderingContext2D::setStrokeStyle(PassRefPtr<CanvasStyle> style)
if (!style)
return;
+ if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentColor(*style))
+ return;
+
if (canvas()->originClean()) {
if (CanvasPattern* pattern = style->canvasPattern()) {
if (!pattern->originClean())
@@ -184,6 +187,7 @@ void CanvasRenderingContext2D::setStrokeStyle(PassRefPtr<CanvasStyle> style)
if (!c)
return;
state().m_strokeStyle->applyStrokeColor(c);
+ state().m_unparsedStrokeColor = String();
}
CanvasStyle* CanvasRenderingContext2D::fillStyle() const
@@ -195,6 +199,9 @@ void CanvasRenderingContext2D::setFillStyle(PassRefPtr<CanvasStyle> style)
{
if (!style)
return;
+
+ if (state().m_fillStyle && state().m_fillStyle->isEquivalentColor(*style))
+ return;
if (canvas()->originClean()) {
if (CanvasPattern* pattern = style->canvasPattern()) {
@@ -208,6 +215,7 @@ void CanvasRenderingContext2D::setFillStyle(PassRefPtr<CanvasStyle> style)
if (!c)
return;
state().m_fillStyle->applyFillColor(c);
+ state().m_unparsedFillColor = String();
}
float CanvasRenderingContext2D::lineWidth() const
@@ -478,7 +486,10 @@ void CanvasRenderingContext2D::setTransform(float m11, float m12, float m21, flo
void CanvasRenderingContext2D::setStrokeColor(const String& color)
{
+ if (color == state().m_unparsedStrokeColor)
+ return;
setStrokeStyle(CanvasStyle::create(color));
+ state().m_unparsedStrokeColor = color;
}
void CanvasRenderingContext2D::setStrokeColor(float grayLevel)
@@ -508,7 +519,10 @@ void CanvasRenderingContext2D::setStrokeColor(float c, float m, float y, float k
void CanvasRenderingContext2D::setFillColor(const String& color)
{
+ if (color == state().m_unparsedFillColor)
+ return;
setFillStyle(CanvasStyle::create(color));
+ state().m_unparsedFillColor = color;
}
void CanvasRenderingContext2D::setFillColor(float grayLevel)
@@ -543,7 +557,12 @@ void CanvasRenderingContext2D::beginPath()
void CanvasRenderingContext2D::closePath()
{
- m_path.closeSubpath();
+ if (m_path.isEmpty())
+ return;
+
+ FloatRect boundRect = m_path.boundingRect();
+ if (boundRect.width() || boundRect.height())
+ m_path.closeSubpath();
}
void CanvasRenderingContext2D::moveTo(float x, float y)
@@ -561,9 +580,11 @@ void CanvasRenderingContext2D::lineTo(float x, float y)
return;
if (!state().m_invertibleCTM)
return;
+
+ FloatPoint p1 = FloatPoint(x, y);
if (!m_path.hasCurrentPoint())
- m_path.moveTo(FloatPoint(x, y));
- else
+ m_path.moveTo(p1);
+ else if (p1 != m_path.currentPoint())
m_path.addLineTo(FloatPoint(x, y));
}
@@ -575,7 +596,10 @@ void CanvasRenderingContext2D::quadraticCurveTo(float cpx, float cpy, float x, f
return;
if (!m_path.hasCurrentPoint())
m_path.moveTo(FloatPoint(cpx, cpy));
- m_path.addQuadCurveTo(FloatPoint(cpx, cpy), FloatPoint(x, y));
+
+ FloatPoint p1 = FloatPoint(x, y);
+ if (p1 != m_path.currentPoint())
+ m_path.addQuadCurveTo(FloatPoint(cpx, cpy), p1);
}
void CanvasRenderingContext2D::bezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y)
@@ -586,22 +610,35 @@ void CanvasRenderingContext2D::bezierCurveTo(float cp1x, float cp1y, float cp2x,
return;
if (!m_path.hasCurrentPoint())
m_path.moveTo(FloatPoint(cp1x, cp1y));
- m_path.addBezierCurveTo(FloatPoint(cp1x, cp1y), FloatPoint(cp2x, cp2y), FloatPoint(x, y));
+
+ FloatPoint p1 = FloatPoint(x, y);
+ if (p1 != m_path.currentPoint())
+ m_path.addBezierCurveTo(FloatPoint(cp1x, cp1y), FloatPoint(cp2x, cp2y), p1);
}
-void CanvasRenderingContext2D::arcTo(float x0, float y0, float x1, float y1, float r, ExceptionCode& ec)
+void CanvasRenderingContext2D::arcTo(float x1, float y1, float x2, float y2, float r, ExceptionCode& ec)
{
ec = 0;
- if (!isfinite(x0) | !isfinite(y0) | !isfinite(x1) | !isfinite(y1) | !isfinite(r))
+ if (!isfinite(x1) | !isfinite(y1) | !isfinite(x2) | !isfinite(y2) | !isfinite(r))
return;
if (r < 0) {
ec = INDEX_SIZE_ERR;
return;
}
+
if (!state().m_invertibleCTM)
return;
- m_path.addArcTo(FloatPoint(x0, y0), FloatPoint(x1, y1), r);
+
+ FloatPoint p1 = FloatPoint(x1, y1);
+ FloatPoint p2 = FloatPoint(x2, y2);
+
+ if (!m_path.hasCurrentPoint())
+ m_path.moveTo(p1);
+ else if (p1 == m_path.currentPoint() || p1 == p2 || !r)
+ lineTo(x1, y1);
+ else
+ m_path.addArcTo(p1, p2, r);
}
void CanvasRenderingContext2D::arc(float x, float y, float r, float sa, float ea, bool anticlockwise, ExceptionCode& ec)
@@ -646,10 +683,27 @@ static bool validateRectForCanvas(float& x, float& y, float& width, float& heigh
void CanvasRenderingContext2D::rect(float x, float y, float width, float height)
{
- if (!validateRectForCanvas(x, y, width, height))
- return;
if (!state().m_invertibleCTM)
return;
+
+ if (!isfinite(x) || !isfinite(y) || !isfinite(width) || !isfinite(height))
+ return;
+
+ if (!width && !height) {
+ m_path.moveTo(FloatPoint(x, y));
+ return;
+ }
+
+ if (width < 0) {
+ width = -width;
+ x -= width;
+ }
+
+ if (height < 0) {
+ height = -height;
+ y -= height;
+ }
+
m_path.addRect(FloatRect(x, y, width, height));
}
@@ -1126,6 +1180,8 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const
if (!sourceCanvas->originClean())
canvas()->setOriginTainted();
+ sourceCanvas->makeRenderingResultsAvailable();
+
c->drawImage(buffer->image(), DeviceColorSpace, destRect, sourceRect, state().m_globalComposite);
willDraw(destRect); // This call comes after drawImage, since the buffer we draw into may be our own, and we need to make sure it is dirty.
// FIXME: Arguably willDraw should become didDraw and occur after drawing calls and not before them to avoid problems like this.
@@ -1344,7 +1400,7 @@ void CanvasRenderingContext2D::willDraw(const FloatRect& r, unsigned options)
dirtyRect = ctm.mapRect(r);
}
- if (options & CanvasWillDrawApplyShadow) {
+ if (options & CanvasWillDrawApplyShadow && alphaChannel(state().m_shadowColor)) {
// The shadow gets applied after transformation
FloatRect shadowRect(dirtyRect);
shadowRect.move(state().m_shadowOffset);
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.h b/WebCore/html/canvas/CanvasRenderingContext2D.h
index 43f3b35..2eac88d 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.h
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.h
@@ -214,6 +214,8 @@ namespace WebCore {
struct State {
State();
+ String m_unparsedStrokeColor;
+ String m_unparsedFillColor;
RefPtr<CanvasStyle> m_strokeStyle;
RefPtr<CanvasStyle> m_fillStyle;
float m_lineWidth;
diff --git a/WebCore/html/canvas/CanvasStyle.cpp b/WebCore/html/canvas/CanvasStyle.cpp
index 67e8201..1ae5236 100644
--- a/WebCore/html/canvas/CanvasStyle.cpp
+++ b/WebCore/html/canvas/CanvasStyle.cpp
@@ -33,6 +33,7 @@
#include "CanvasGradient.h"
#include "CanvasPattern.h"
#include "GraphicsContext.h"
+#include <wtf/Assertions.h>
#include <wtf/PassRefPtr.h>
#if PLATFORM(CG)
@@ -120,6 +121,29 @@ PassRefPtr<CanvasStyle> CanvasStyle::create(PassRefPtr<CanvasPattern> pattern)
return adoptRef(new CanvasStyle(pattern));
}
+bool CanvasStyle::isEquivalentColor(const CanvasStyle& other) const
+{
+ if (m_type != other.m_type)
+ return false;
+
+ switch (m_type) {
+ case CanvasStyle::RGBA:
+ return m_rgba == other.m_rgba;
+ case CanvasStyle::CMYKA:
+ return m_cmyka.c == other.m_cmyka.c
+ && m_cmyka.m == other.m_cmyka.m
+ && m_cmyka.y == other.m_cmyka.y
+ && m_cmyka.k == other.m_cmyka.k
+ && m_cmyka.a == other.m_cmyka.a;
+ case CanvasStyle::Gradient:
+ case CanvasStyle::ImagePattern:
+ return false;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
void CanvasStyle::applyStrokeColor(GraphicsContext* context)
{
if (!context)
diff --git a/WebCore/html/canvas/CanvasStyle.h b/WebCore/html/canvas/CanvasStyle.h
index 18e55cf..76ba6ef 100644
--- a/WebCore/html/canvas/CanvasStyle.h
+++ b/WebCore/html/canvas/CanvasStyle.h
@@ -55,6 +55,8 @@ namespace WebCore {
void applyFillColor(GraphicsContext*);
void applyStrokeColor(GraphicsContext*);
+ bool isEquivalentColor(const CanvasStyle&) const;
+
private:
CanvasStyle(RGBA32 rgba);
CanvasStyle(float grayLevel);
diff --git a/WebCore/html/canvas/Float32Array.idl b/WebCore/html/canvas/Float32Array.idl
index 651e74f..5a939ca 100644
--- a/WebCore/html/canvas/Float32Array.idl
+++ b/WebCore/html/canvas/Float32Array.idl
@@ -33,7 +33,8 @@ module html {
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
- CustomToJS
+ CustomToJS,
+ DontCheckEnums
] Float32Array : ArrayBufferView {
const unsigned int BYTES_PER_ELEMENT = 4;
diff --git a/WebCore/html/canvas/Int16Array.idl b/WebCore/html/canvas/Int16Array.idl
index 095611b..02417f8 100644
--- a/WebCore/html/canvas/Int16Array.idl
+++ b/WebCore/html/canvas/Int16Array.idl
@@ -32,7 +32,8 @@ module html {
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
- CustomToJS
+ CustomToJS,
+ DontCheckEnums
] Int16Array : ArrayBufferView {
const unsigned int BYTES_PER_ELEMENT = 2;
diff --git a/WebCore/html/canvas/Int32Array.idl b/WebCore/html/canvas/Int32Array.idl
index 9d1e8ee..6977d00 100644
--- a/WebCore/html/canvas/Int32Array.idl
+++ b/WebCore/html/canvas/Int32Array.idl
@@ -33,7 +33,8 @@ module html {
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
- CustomToJS
+ CustomToJS,
+ DontCheckEnums
] Int32Array : ArrayBufferView {
const unsigned int BYTES_PER_ELEMENT = 4;
diff --git a/WebCore/html/canvas/Int8Array.idl b/WebCore/html/canvas/Int8Array.idl
index 43c83f5..4dba9e4 100644
--- a/WebCore/html/canvas/Int8Array.idl
+++ b/WebCore/html/canvas/Int8Array.idl
@@ -33,7 +33,8 @@ module html {
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
- CustomToJS
+ CustomToJS,
+ DontCheckEnums
] Int8Array : ArrayBufferView {
const unsigned int BYTES_PER_ELEMENT = 1;
diff --git a/WebCore/html/canvas/Uint16Array.idl b/WebCore/html/canvas/Uint16Array.idl
index 4c369a0..de1e5e0 100644
--- a/WebCore/html/canvas/Uint16Array.idl
+++ b/WebCore/html/canvas/Uint16Array.idl
@@ -33,7 +33,8 @@ module html {
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
- CustomToJS
+ CustomToJS,
+ DontCheckEnums
] Uint16Array : ArrayBufferView {
const unsigned int BYTES_PER_ELEMENT = 2;
diff --git a/WebCore/html/canvas/Uint32Array.idl b/WebCore/html/canvas/Uint32Array.idl
index 25f5b71..ce632dd 100644
--- a/WebCore/html/canvas/Uint32Array.idl
+++ b/WebCore/html/canvas/Uint32Array.idl
@@ -33,7 +33,8 @@ module html {
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
- CustomToJS
+ CustomToJS,
+ DontCheckEnums
] Uint32Array : ArrayBufferView {
const unsigned int BYTES_PER_ELEMENT = 4;
diff --git a/WebCore/html/canvas/Uint8Array.idl b/WebCore/html/canvas/Uint8Array.idl
index 76b8cdd..c520844 100644
--- a/WebCore/html/canvas/Uint8Array.idl
+++ b/WebCore/html/canvas/Uint8Array.idl
@@ -33,7 +33,8 @@ module html {
HasNumericIndexGetter,
HasCustomIndexSetter,
GenerateNativeConverter,
- CustomToJS
+ CustomToJS,
+ DontCheckEnums
] Uint8Array : ArrayBufferView {
const unsigned int BYTES_PER_ELEMENT = 1;
diff --git a/WebCore/html/canvas/WebGLBuffer.cpp b/WebCore/html/canvas/WebGLBuffer.cpp
index e71a12b..e449052 100644
--- a/WebCore/html/canvas/WebGLBuffer.cpp
+++ b/WebCore/html/canvas/WebGLBuffer.cpp
@@ -74,6 +74,35 @@ bool WebGLBuffer::associateBufferData(int size)
return false;
}
+bool WebGLBuffer::associateBufferData(ArrayBuffer* array)
+{
+ if (!m_target)
+ return false;
+ if (!array)
+ return false;
+
+ if (m_target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
+ clearCachedMaxIndices();
+ m_byteLength = array->byteLength();
+ // We must always clone the incoming data because client-side
+ // modifications without calling bufferData or bufferSubData
+ // must never be able to change the validation results.
+ m_elementArrayBuffer = ArrayBuffer::create(array);
+ if (!m_elementArrayBuffer) {
+ m_byteLength = 0;
+ return false;
+ }
+ return true;
+ }
+
+ if (m_target == GraphicsContext3D::ARRAY_BUFFER) {
+ m_byteLength = array->byteLength();
+ return true;
+ }
+
+ return false;
+}
+
bool WebGLBuffer::associateBufferData(ArrayBufferView* array)
{
if (!m_target)
@@ -103,6 +132,39 @@ bool WebGLBuffer::associateBufferData(ArrayBufferView* array)
return false;
}
+bool WebGLBuffer::associateBufferSubData(long offset, ArrayBuffer* array)
+{
+ if (!m_target)
+ return false;
+ if (!array)
+ return false;
+
+ if (m_target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) {
+ clearCachedMaxIndices();
+
+ // We need to protect against integer overflow with these tests
+ if (offset < 0)
+ return false;
+
+ unsigned long uoffset = static_cast<unsigned long>(offset);
+ if (uoffset > m_byteLength || array->byteLength() > m_byteLength - uoffset)
+ return false;
+
+ if (!m_elementArrayBuffer)
+ return false;
+
+ memcpy(static_cast<unsigned char*>(m_elementArrayBuffer->data()) + offset,
+ static_cast<unsigned char*>(array->data()),
+ array->byteLength());
+ return true;
+ }
+
+ if (m_target == GraphicsContext3D::ARRAY_BUFFER)
+ return array->byteLength() + offset <= m_byteLength;
+
+ return false;
+}
+
bool WebGLBuffer::associateBufferSubData(long offset, ArrayBufferView* array)
{
if (!m_target)
diff --git a/WebCore/html/canvas/WebGLBuffer.h b/WebCore/html/canvas/WebGLBuffer.h
index e1fec47..1280cf9 100644
--- a/WebCore/html/canvas/WebGLBuffer.h
+++ b/WebCore/html/canvas/WebGLBuffer.h
@@ -41,7 +41,9 @@ namespace WebCore {
static PassRefPtr<WebGLBuffer> create(WebGLRenderingContext*);
bool associateBufferData(int size);
+ bool associateBufferData(ArrayBuffer* array);
bool associateBufferData(ArrayBufferView* array);
+ bool associateBufferSubData(long offset, ArrayBuffer* array);
bool associateBufferSubData(long offset, ArrayBufferView* array);
unsigned byteLength() const;
diff --git a/WebCore/html/canvas/WebGLRenderingContext.cpp b/WebCore/html/canvas/WebGLRenderingContext.cpp
index a82a4ac4..f567ac8 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -115,12 +115,12 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
m_context->getIntegerv(GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE, &implementationColorReadType);
m_implementationColorReadType = implementationColorReadType;
- int maxTextureSize = 0;
- m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize);
- m_maxTextureSize = maxTextureSize;
- int maxCubeMapTextureSize = 0;
- m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapTextureSize);
- m_maxCubeMapTextureSize = maxCubeMapTextureSize;
+ m_maxTextureSize = 0;
+ m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize);
+ m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize);
+ m_maxCubeMapTextureSize = 0;
+ m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize);
+ m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize);
if (!isGLES2Compliant()) {
createFallbackBlackTextures1x1();
@@ -141,17 +141,23 @@ void WebGLRenderingContext::markContextChanged()
RenderBox* renderBox = canvas()->renderBox();
if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing())
renderBox->layer()->rendererContentChanged();
- else {
#endif
- if (!m_markedCanvasDirty) {
- // Make sure the canvas's image buffer is allocated.
- canvas()->buffer();
- canvas()->willDraw(FloatRect(0, 0, canvas()->width(), canvas()->height()));
- m_markedCanvasDirty = true;
- }
-#if USE(ACCELERATED_COMPOSITING)
+ if (!m_markedCanvasDirty) {
+ // Make sure the canvas's image buffer is allocated.
+ canvas()->buffer();
+ canvas()->willDraw(FloatRect(0, 0, canvas()->width(), canvas()->height()));
+ m_markedCanvasDirty = true;
}
-#endif
+}
+
+bool WebGLRenderingContext::paintRenderingResultsToCanvas()
+{
+ if (m_markedCanvasDirty) {
+ m_markedCanvasDirty = false;
+ m_context->paintRenderingResultsToCanvas(this);
+ return true;
+ }
+ return false;
}
void WebGLRenderingContext::beginPaint()
@@ -293,17 +299,20 @@ void WebGLRenderingContext::bindTexture(unsigned long target, WebGLTexture* text
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
- if (target == GraphicsContext3D::TEXTURE_2D)
+ int maxLevel = 0;
+ if (target == GraphicsContext3D::TEXTURE_2D) {
m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture;
- else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP)
+ maxLevel = m_maxTextureLevel;
+ } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture;
- else {
+ maxLevel = m_maxCubeMapTextureLevel;
+ } else {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
return;
}
m_context->bindTexture(target, texture);
if (!isGLES2Compliant() && texture)
- texture->setTarget(target);
+ texture->setTarget(target, maxLevel);
cleanupAfterGraphicsCall(false);
}
@@ -349,22 +358,11 @@ void WebGLRenderingContext::blendFuncSeparate(unsigned long srcRGB, unsigned lon
void WebGLRenderingContext::bufferData(unsigned long target, int size, unsigned long usage, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!isGLES2Compliant()) {
- if (!validateBufferDataUsage(usage))
- return;
- }
- if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && m_boundElementArrayBuffer) {
- if (!m_boundElementArrayBuffer->associateBufferData(size)) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- } else if (target == GraphicsContext3D::ARRAY_BUFFER && m_boundArrayBuffer) {
- if (!m_boundArrayBuffer->associateBufferData(size)) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- } else {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
+ if (!buffer)
+ return;
+ if (!buffer->associateBufferData(size)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
@@ -372,25 +370,29 @@ void WebGLRenderingContext::bufferData(unsigned long target, int size, unsigned
cleanupAfterGraphicsCall(false);
}
-void WebGLRenderingContext::bufferData(unsigned long target, ArrayBufferView* data, unsigned long usage, ExceptionCode& ec)
+void WebGLRenderingContext::bufferData(unsigned long target, ArrayBuffer* data, unsigned long usage, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (!isGLES2Compliant()) {
- if (!validateBufferDataUsage(usage))
- return;
+ WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
+ if (!buffer)
+ return;
+ if (!buffer->associateBufferData(data)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
}
- if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && m_boundElementArrayBuffer) {
- if (!m_boundElementArrayBuffer->associateBufferData(data)) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- } else if (target == GraphicsContext3D::ARRAY_BUFFER && m_boundArrayBuffer) {
- if (!m_boundArrayBuffer->associateBufferData(data)) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- } else {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+
+ m_context->bufferData(target, data, usage);
+ cleanupAfterGraphicsCall(false);
+}
+
+void WebGLRenderingContext::bufferData(unsigned long target, ArrayBufferView* data, unsigned long usage, ExceptionCode& ec)
+{
+ UNUSED_PARAM(ec);
+ WebGLBuffer* buffer = validateBufferDataParameters(target, usage);
+ if (!buffer)
+ return;
+ if (!buffer->associateBufferData(data)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
@@ -398,21 +400,29 @@ void WebGLRenderingContext::bufferData(unsigned long target, ArrayBufferView* da
cleanupAfterGraphicsCall(false);
}
+void WebGLRenderingContext::bufferSubData(unsigned long target, long offset, ArrayBuffer* data, ExceptionCode& ec)
+{
+ UNUSED_PARAM(ec);
+ WebGLBuffer* buffer = validateBufferDataParameters(target, GraphicsContext3D::STATIC_DRAW);
+ if (!buffer)
+ return;
+ if (!buffer->associateBufferSubData(offset, data)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return;
+ }
+
+ m_context->bufferSubData(target, offset, data);
+ cleanupAfterGraphicsCall(false);
+}
+
void WebGLRenderingContext::bufferSubData(unsigned long target, long offset, ArrayBufferView* data, ExceptionCode& ec)
{
UNUSED_PARAM(ec);
- if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER && m_boundElementArrayBuffer) {
- if (!m_boundElementArrayBuffer->associateBufferSubData(offset, data)) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- } else if (target == GraphicsContext3D::ARRAY_BUFFER && m_boundArrayBuffer) {
- if (!m_boundArrayBuffer->associateBufferSubData(offset, data)) {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
- return;
- }
- } else {
- m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ WebGLBuffer* buffer = validateBufferDataParameters(target, GraphicsContext3D::STATIC_DRAW);
+ if (!buffer)
+ return;
+ if (!buffer->associateBufferSubData(offset, data)) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return;
}
@@ -507,10 +517,8 @@ void WebGLRenderingContext::copyTexImage2D(unsigned long target, long level, uns
// FIXME: if the framebuffer is not complete, none of the below should be executed.
WebGLTexture* tex = getTextureBinding(target);
if (!isGLES2Compliant()) {
- if (tex && !level) // only for level 0
- tex->setSize(target, width, height);
if (tex)
- tex->setInternalFormat(internalformat);
+ tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
}
if (m_framebufferBinding && tex)
m_framebufferBinding->onAttachedObjectChange(tex);
@@ -1082,18 +1090,22 @@ void WebGLRenderingContext::frontFace(unsigned long mode)
void WebGLRenderingContext::generateMipmap(unsigned long target)
{
+ RefPtr<WebGLTexture> tex;
if (!isGLES2Compliant()) {
- RefPtr<WebGLTexture> tex = 0;
if (target == GraphicsContext3D::TEXTURE_2D)
tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding;
else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP)
tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding;
- if (tex && tex->isNPOT()) {
+ if (tex && !tex->canGenerateMipmaps()) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
return;
}
}
m_context->generateMipmap(target);
+ if (!isGLES2Compliant()) {
+ if (tex)
+ tex->generateMipmapLevelInfo();
+ }
cleanupAfterGraphicsCall(false);
}
@@ -1337,7 +1349,8 @@ WebGLGetInfo WebGLRenderingContext::getParameter(unsigned long pname, ExceptionC
case GraphicsContext3D::MAX_VIEWPORT_DIMS:
return getWebGLIntArrayParameter(pname);
case GraphicsContext3D::NUM_COMPRESSED_TEXTURE_FORMATS:
- return getLongParameter(pname);
+ // WebGL 1.0 specifies that there are no compressed texture formats.
+ return WebGLGetInfo(static_cast<long>(0));
case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS:
// FIXME: should we always return 0 for this?
return getLongParameter(pname);
@@ -2082,10 +2095,8 @@ void WebGLRenderingContext::texImage2DBase(unsigned target, unsigned level, unsi
border, format, type, pixels);
WebGLTexture* tex = getTextureBinding(target);
if (!isGLES2Compliant()) {
- if (tex && !level) // only for level 0
- tex->setSize(target, width, height);
if (tex)
- tex->setInternalFormat(internalformat);
+ tex->setLevelInfo(target, level, internalformat, width, height, type);
}
if (m_framebufferBinding && tex)
m_framebufferBinding->onAttachedObjectChange(tex);
@@ -3369,9 +3380,6 @@ bool WebGLRenderingContext::validateTexFuncParameters(unsigned long target, long
if (!validateTexFuncFormatAndType(format, type))
return false;
- if (isGLES2Compliant())
- return true;
-
if (width < 0 || height < 0 || level < 0) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return false;
@@ -3379,7 +3387,7 @@ bool WebGLRenderingContext::validateTexFuncParameters(unsigned long target, long
switch (target) {
case GraphicsContext3D::TEXTURE_2D:
- if (width > m_maxTextureSize || height > m_maxTextureSize) {
+ if (width > m_maxTextureSize || height > m_maxTextureSize || level > m_maxTextureLevel) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return false;
}
@@ -3390,7 +3398,7 @@ bool WebGLRenderingContext::validateTexFuncParameters(unsigned long target, long
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
- if (width != height || width > m_maxCubeMapTextureSize) {
+ if (width != height || width > m_maxCubeMapTextureSize || level > m_maxCubeMapTextureLevel) {
m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
return false;
}
@@ -3592,16 +3600,32 @@ bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLo
return true;
}
-bool WebGLRenderingContext::validateBufferDataUsage(unsigned long usage)
+WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(unsigned long target, unsigned long usage)
{
+ WebGLBuffer* buffer = 0;
+ switch (target) {
+ case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
+ buffer = m_boundElementArrayBuffer.get();
+ break;
+ case GraphicsContext3D::ARRAY_BUFFER:
+ buffer = m_boundArrayBuffer.get();
+ break;
+ default:
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
+ return 0;
+ }
+ if (!buffer) {
+ m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
+ return 0;
+ }
switch (usage) {
case GraphicsContext3D::STREAM_DRAW:
case GraphicsContext3D::STATIC_DRAW:
case GraphicsContext3D::DYNAMIC_DRAW:
- return true;
+ return buffer;
}
m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
- return false;
+ return 0;
}
void WebGLRenderingContext::vertexAttribfImpl(unsigned long index, int expectedSize, float v0, float v1, float v2, float v3)
diff --git a/WebCore/html/canvas/WebGLRenderingContext.h b/WebCore/html/canvas/WebGLRenderingContext.h
index d03d972..fa9ffdb 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/WebCore/html/canvas/WebGLRenderingContext.h
@@ -77,7 +77,9 @@ class WebKitCSSMatrix;
void blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha);
void bufferData(unsigned long target, int size, unsigned long usage, ExceptionCode&);
+ void bufferData(unsigned long target, ArrayBuffer* data, unsigned long usage, ExceptionCode&);
void bufferData(unsigned long target, ArrayBufferView* data, unsigned long usage, ExceptionCode&);
+ void bufferSubData(unsigned long target, long offset, ArrayBuffer* data, ExceptionCode&);
void bufferSubData(unsigned long target, long offset, ArrayBufferView* data, ExceptionCode&);
unsigned long checkFramebufferStatus(unsigned long target);
@@ -304,6 +306,10 @@ class WebKitCSSMatrix;
void reshape(int width, int height);
+ // Return value true indicates canvas is updated during the call,
+ // false indicates no updates.
+ bool paintRenderingResultsToCanvas();
+
// Helpers for notification about paint events.
void beginPaint();
void endPaint();
@@ -410,8 +416,10 @@ class WebKitCSSMatrix;
RefPtr<WebGLTexture> m_blackTexture2D;
RefPtr<WebGLTexture> m_blackTextureCubeMap;
- long m_maxTextureSize;
- long m_maxCubeMapTextureSize;
+ int m_maxTextureSize;
+ int m_maxCubeMapTextureSize;
+ int m_maxTextureLevel;
+ int m_maxCubeMapTextureLevel;
int m_packAlignment;
int m_unpackAlignment;
@@ -501,8 +509,9 @@ class WebKitCSSMatrix;
bool validateUniformMatrixParameters(const WebGLUniformLocation* location, bool transpose, Float32Array* v, int mod);
bool validateUniformMatrixParameters(const WebGLUniformLocation* location, bool transpose, void* v, int size, int mod);
- // Helper function to validate usage for bufferData.
- bool validateBufferDataUsage(unsigned long);
+ // Helper function to validate parameters for bufferData.
+ // Return the current bound buffer to target, or 0 if parameters are invalid.
+ WebGLBuffer* validateBufferDataParameters(unsigned long target, unsigned long usage);
// Helper functions for vertexAttribNf{v}.
void vertexAttribfImpl(unsigned long index, int expectedSize, float v0, float v1, float v2, float v3);
diff --git a/WebCore/html/canvas/WebGLRenderingContext.idl b/WebCore/html/canvas/WebGLRenderingContext.idl
index 1ea4c6d..654c7aa 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.idl
+++ b/WebCore/html/canvas/WebGLRenderingContext.idl
@@ -28,7 +28,8 @@ module html {
interface [
Conditional=3D_CANVAS,
InterfaceUUID=98fb48ae-7216-489c-862b-8e1217fc4443,
- ImplementationUUID=ab4f0781-152f-450e-9546-5b3987491a54
+ ImplementationUUID=ab4f0781-152f-450e-9546-5b3987491a54,
+ DontCheckEnums
] WebGLRenderingContext : CanvasRenderingContext {
/* ClearBufferMask */
@@ -477,9 +478,10 @@ module html {
void blendEquationSeparate(in unsigned long modeRGB, in unsigned long modeAlpha);
void blendFunc(in unsigned long sfactor, in unsigned long dfactor);
void blendFuncSeparate(in unsigned long srcRGB, in unsigned long dstRGB, in unsigned long srcAlpha, in unsigned long dstAlpha);
-
+ void bufferData(in unsigned long target, in ArrayBuffer data, in unsigned long usage) raises (DOMException);
void bufferData(in unsigned long target, in ArrayBufferView data, in unsigned long usage) raises (DOMException);
void bufferData(in unsigned long target, in long size, in unsigned long usage) raises (DOMException);
+ void bufferSubData(in unsigned long target, in long offset, in ArrayBuffer data) raises (DOMException);
void bufferSubData(in unsigned long target, in long offset, in ArrayBufferView data) raises (DOMException);
unsigned long checkFramebufferStatus(in unsigned long target);
diff --git a/WebCore/html/canvas/WebGLTexture.cpp b/WebCore/html/canvas/WebGLTexture.cpp
index 1cc7d5d..d832038 100644
--- a/WebCore/html/canvas/WebGLTexture.cpp
+++ b/WebCore/html/canvas/WebGLTexture.cpp
@@ -45,32 +45,39 @@ WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx)
, m_magFilter(GraphicsContext3D::LINEAR)
, m_wrapS(GraphicsContext3D::REPEAT)
, m_wrapT(GraphicsContext3D::REPEAT)
- , m_internalFormat(0)
, m_isNPOT(false)
+ , m_isComplete(false)
, m_needToUseBlackTexture(false)
{
setObject(context()->graphicsContext3D()->createTexture());
- for (int ii = 0; ii < 6; ++ii) {
- m_width[ii] = 0;
- m_height[ii] = 0;
- }
}
-void WebGLTexture::setTarget(unsigned long target)
+void WebGLTexture::setTarget(unsigned long target, int maxLevel)
{
+ if (!object())
+ return;
// Target is finalized the first time bindTexture() is called.
if (m_target)
return;
switch (target) {
case GraphicsContext3D::TEXTURE_2D:
+ m_target = target;
+ m_info.resize(1);
+ m_info[0].resize(maxLevel);
+ break;
case GraphicsContext3D::TEXTURE_CUBE_MAP:
m_target = target;
+ m_info.resize(6);
+ for (int ii = 0; ii < 6; ++ii)
+ m_info[ii].resize(maxLevel);
break;
}
}
void WebGLTexture::setParameteri(unsigned long pname, int param)
{
+ if (!object() || !m_target)
+ return;
switch (pname) {
case GraphicsContext3D::TEXTURE_MIN_FILTER:
switch (param) {
@@ -113,88 +120,195 @@ void WebGLTexture::setParameteri(unsigned long pname, int param)
default:
return;
}
- updateNPOTStates();
+ update();
}
void WebGLTexture::setParameterf(unsigned long pname, float param)
{
+ if (!object() || !m_target)
+ return;
int iparam = static_cast<int>(param);
setParameteri(pname, iparam);
}
-void WebGLTexture::setSize(unsigned long target, unsigned width, unsigned height)
+void WebGLTexture::setLevelInfo(unsigned long target, int level, unsigned long internalFormat, int width, int height, unsigned long type)
{
- if (!width || !height)
+ if (!object() || !m_target)
return;
- int iTarget = -1;
+ // We assume level, internalFormat, width, height, and type have all been
+ // validated already.
+ int index = mapTargetToIndex(target);
+ if (index < 0)
+ return;
+ m_info[index][level].setInfo(internalFormat, width, height, type);
+ update();
+}
+
+void WebGLTexture::generateMipmapLevelInfo()
+{
+ if (!object() || !m_target)
+ return;
+ if (!canGenerateMipmaps())
+ return;
+ if (m_isComplete)
+ return;
+ for (size_t ii = 0; ii < m_info.size(); ++ii) {
+ const LevelInfo& info0 = m_info[ii][0];
+ int width = info0.width;
+ int height = info0.height;
+ int levelCount = computeLevelCount(width, height);
+ for (int level = 1; level < levelCount; ++level) {
+ width = std::max(1, width >> 1);
+ height = std::max(1, height >> 1);
+ LevelInfo& info = m_info[ii][level];
+ info.setInfo(info0.internalFormat, width, height, info0.type);
+ }
+ }
+ m_isComplete = true;
+}
+
+unsigned long WebGLTexture::getInternalFormat() const
+{
+ if (!object() || !m_target)
+ return 0;
+ return m_info[0][0].internalFormat;
+}
+
+bool WebGLTexture::isNPOT(unsigned width, unsigned height)
+{
+ if (!width || !height)
+ return false;
+ if ((width & (width - 1)) || (height & (height - 1)))
+ return true;
+ return false;
+}
+
+bool WebGLTexture::isNPOT() const
+{
+ if (!object())
+ return false;
+ return m_isNPOT;
+}
+
+bool WebGLTexture::needToUseBlackTexture() const
+{
+ if (!object())
+ return false;
+ return m_needToUseBlackTexture;
+}
+
+void WebGLTexture::_deleteObject(Platform3DObject object)
+{
+ context()->graphicsContext3D()->deleteTexture(object);
+}
+
+int WebGLTexture::mapTargetToIndex(unsigned long target)
+{
if (m_target == GraphicsContext3D::TEXTURE_2D) {
if (target == GraphicsContext3D::TEXTURE_2D)
- iTarget = 0;
- } else if (m_target == GraphicsContext3D::TEXTURE_CUBE_MAP && width == height) {
+ return 0;
+ } else if (m_target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
switch (target) {
case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
- iTarget = 0;
- break;
+ return 0;
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
- iTarget = 1;
- break;
+ return 1;
case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
- iTarget = 2;
- break;
+ return 2;
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
- iTarget = 3;
- break;
+ return 3;
case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
- iTarget = 4;
- break;
+ return 4;
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
- iTarget = 5;
- break;
+ return 5;
}
}
- if (iTarget < 0)
- return;
- m_width[iTarget] = width;
- m_height[iTarget] = height;
- updateNPOTStates();
+ return -1;
}
-bool WebGLTexture::isNPOT(unsigned width, unsigned height)
+bool WebGLTexture::canGenerateMipmaps()
{
- if (!width || !height)
+ if (isNPOT())
return false;
- if ((width & (width - 1)) || (height & (height - 1)))
- return true;
- return false;
+ const LevelInfo& first = m_info[0][0];
+ for (size_t ii = 0; ii < m_info.size(); ++ii) {
+ const LevelInfo& info = m_info[ii][0];
+ if (!info.valid
+ || info.width != first.width || info.height != first.height
+ || info.internalFormat != first.internalFormat || info.type != first.type)
+ return false;
+ }
+ return true;
}
-void WebGLTexture::_deleteObject(Platform3DObject object)
+int WebGLTexture::computeLevelCount(int width, int height)
{
- context()->graphicsContext3D()->deleteTexture(object);
+ // return 1 + log2Floor(std::max(width, height));
+ int n = std::max(width, height);
+ if (n <= 0)
+ return 0;
+ int log = 0;
+ int value = n;
+ for (int ii = 4; ii >= 0; --ii) {
+ int shift = (1 << ii);
+ int x = (value >> shift);
+ if (x) {
+ value = x;
+ log += shift;
+ }
+ }
+ ASSERT(value == 1);
+ return log + 1;
}
-void WebGLTexture::updateNPOTStates()
+void WebGLTexture::update()
{
- int numTargets = 0;
- if (m_target == GraphicsContext3D::TEXTURE_2D)
- numTargets = 1;
- else if (m_target == GraphicsContext3D::TEXTURE_CUBE_MAP)
- numTargets = 6;
m_isNPOT = false;
- unsigned w0 = m_width[0], h0 = m_height[0];
- for (int ii = 0; ii < numTargets; ++ii) {
- if (ii && (!m_width[ii] || !m_height[ii] || m_width[ii] != w0 || m_height[ii] != h0)) {
- // We only set NPOT for complete cube map textures.
- m_isNPOT = false;
+ for (size_t ii = 0; ii < m_info.size(); ++ii) {
+ if (isNPOT(m_info[ii][0].width, m_info[ii][0].height)) {
+ m_isNPOT = true;
break;
}
- if (isNPOT(m_width[ii], m_height[ii]))
- m_isNPOT = true;
}
+ m_isComplete = true;
+ const LevelInfo& first = m_info[0][0];
+ int levelCount = computeLevelCount(first.width, first.height);
+ if (levelCount < 1)
+ m_isComplete = false;
+ else {
+ for (size_t ii = 0; ii < m_info.size() && m_isComplete; ++ii) {
+ const LevelInfo& info0 = m_info[ii][0];
+ if (!info0.valid
+ || info0.width != first.width || info0.height != first.height
+ || info0.internalFormat != first.internalFormat || info0.type != first.type) {
+ m_isComplete = false;
+ break;
+ }
+ int width = info0.width;
+ int height = info0.height;
+ for (int level = 1; level < levelCount; ++level) {
+ width = std::max(1, width >> 1);
+ height = std::max(1, height >> 1);
+ const LevelInfo& info = m_info[ii][level];
+ if (!info.valid
+ || info.width != width || info.height != height
+ || info.internalFormat != info0.internalFormat || info.type != info0.type) {
+ m_isComplete = false;
+ break;
+ }
+
+ }
+ }
+ }
+
m_needToUseBlackTexture = false;
+ // NPOT
if (m_isNPOT && ((m_minFilter != GraphicsContext3D::NEAREST && m_minFilter != GraphicsContext3D::LINEAR)
|| m_wrapS != GraphicsContext3D::CLAMP_TO_EDGE || m_wrapT != GraphicsContext3D::CLAMP_TO_EDGE))
m_needToUseBlackTexture = true;
+ // Completeness
+ if (!m_isComplete && m_minFilter != GraphicsContext3D::NEAREST && m_minFilter != GraphicsContext3D::LINEAR)
+ m_needToUseBlackTexture = true;
}
}
diff --git a/WebCore/html/canvas/WebGLTexture.h b/WebCore/html/canvas/WebGLTexture.h
index 4d16b59..d4a32f0 100644
--- a/WebCore/html/canvas/WebGLTexture.h
+++ b/WebCore/html/canvas/WebGLTexture.h
@@ -30,6 +30,7 @@
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
namespace WebCore {
@@ -47,19 +48,26 @@ namespace WebCore {
cubeMapRWrapModeInitialized = initialized;
}
- void setTarget(unsigned long);
+ void setTarget(unsigned long target, int maxLevel);
void setParameteri(unsigned long pname, int param);
void setParameterf(unsigned long pname, float param);
- void setSize(unsigned long target, unsigned width, unsigned height);
- void setInternalFormat(unsigned long internalformat) { m_internalFormat = internalformat; }
- unsigned long getInternalFormat() const { return m_internalFormat; }
+ void setLevelInfo(unsigned long target, int level, unsigned long internalFormat, int width, int height, unsigned long type);
+ bool canGenerateMipmaps();
+ // Generate all level information.
+ void generateMipmapLevelInfo();
+
+ unsigned long getInternalFormat() const;
+
+ // Whether width/height is NotPowerOfTwo.
static bool isNPOT(unsigned, unsigned);
- bool isNPOT() const { return m_isNPOT; }
+ bool isNPOT() const;
// Determine if texture sampling should always return [0, 0, 0, 1] (OpenGL ES 2.0 Sec 3.8.2).
- bool needToUseBlackTexture() const { return m_needToUseBlackTexture; }
+ bool needToUseBlackTexture() const;
+
+ static int computeLevelCount(int width, int height);
protected:
WebGLTexture(WebGLRenderingContext*);
@@ -69,7 +77,9 @@ namespace WebCore {
private:
virtual bool isTexture() const { return true; }
- void updateNPOTStates();
+ void update();
+
+ int mapTargetToIndex(unsigned long);
bool cubeMapRWrapModeInitialized;
@@ -80,12 +90,37 @@ namespace WebCore {
int m_wrapS;
int m_wrapT;
- unsigned long m_internalFormat;
-
- unsigned m_width[6];
- unsigned m_height[6];
+ class LevelInfo {
+ public:
+ LevelInfo()
+ : valid(false)
+ , internalFormat(0)
+ , width(0)
+ , height(0)
+ , type(0)
+ {
+ }
+
+ void setInfo(unsigned long internalFmt, int w, int h, unsigned long tp)
+ {
+ valid = true;
+ internalFormat = internalFmt;
+ width = w;
+ height = h;
+ type = tp;
+ }
+
+ bool valid;
+ unsigned long internalFormat;
+ int width;
+ int height;
+ unsigned long type;
+ };
+
+ Vector<Vector<LevelInfo> > m_info;
bool m_isNPOT;
+ bool m_isComplete;
bool m_needToUseBlackTexture;
};