#include "config.h"
#if ENABLE(3D_CANVAS)
#include "WebGLTexture.h"
#include "WebGLRenderingContext.h"
namespace WebCore {
PassRefPtr<WebGLTexture> WebGLTexture::create(WebGLRenderingContext* ctx)
{
return adoptRef(new WebGLTexture(ctx));
}
WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx)
: CanvasObject(ctx)
, cubeMapRWrapModeInitialized(false)
, m_target(0)
, m_minFilter(GraphicsContext3D::NEAREST_MIPMAP_LINEAR)
, m_magFilter(GraphicsContext3D::LINEAR)
, m_wrapS(GraphicsContext3D::REPEAT)
, m_wrapT(GraphicsContext3D::REPEAT)
, m_internalFormat(0)
, m_isNPOT(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)
{
if (m_target)
return;
switch (target) {
case GraphicsContext3D::TEXTURE_2D:
case GraphicsContext3D::TEXTURE_CUBE_MAP:
m_target = target;
break;
}
}
void WebGLTexture::setParameteri(unsigned long pname, int param)
{
switch (pname) {
case GraphicsContext3D::TEXTURE_MIN_FILTER:
switch (param) {
case GraphicsContext3D::NEAREST:
case GraphicsContext3D::LINEAR:
case GraphicsContext3D::NEAREST_MIPMAP_NEAREST:
case GraphicsContext3D::LINEAR_MIPMAP_NEAREST:
case GraphicsContext3D::NEAREST_MIPMAP_LINEAR:
case GraphicsContext3D::LINEAR_MIPMAP_LINEAR:
m_minFilter = param;
break;
}
break;
case GraphicsContext3D::TEXTURE_MAG_FILTER:
switch (param) {
case GraphicsContext3D::NEAREST:
case GraphicsContext3D::LINEAR:
m_magFilter = param;
break;
}
break;
case GraphicsContext3D::TEXTURE_WRAP_S:
switch (param) {
case GraphicsContext3D::CLAMP_TO_EDGE:
case GraphicsContext3D::MIRRORED_REPEAT:
case GraphicsContext3D::REPEAT:
m_wrapS = param;
break;
}
break;
case GraphicsContext3D::TEXTURE_WRAP_T:
switch (param) {
case GraphicsContext3D::CLAMP_TO_EDGE:
case GraphicsContext3D::MIRRORED_REPEAT:
case GraphicsContext3D::REPEAT:
m_wrapT = param;
break;
}
break;
default:
return;
}
updateNPOTStates();
}
void WebGLTexture::setParameterf(unsigned long pname, float param)
{
int iparam = static_cast<int>(param);
setParameteri(pname, iparam);
}
void WebGLTexture::setSize(unsigned long target, unsigned width, unsigned height)
{
if (!width || !height)
return;
int iTarget = -1;
if (m_target == GraphicsContext3D::TEXTURE_2D) {
if (target == GraphicsContext3D::TEXTURE_2D)
iTarget = 0;
} else if (m_target == GraphicsContext3D::TEXTURE_CUBE_MAP && width == height) {
switch (target) {
case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
iTarget = 0;
break;
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
iTarget = 1;
break;
case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
iTarget = 2;
break;
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
iTarget = 3;
break;
case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
iTarget = 4;
break;
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
iTarget = 5;
break;
}
}
if (iTarget < 0)
return;
m_width[iTarget] = width;
m_height[iTarget] = height;
updateNPOTStates();
}
bool WebGLTexture::isNPOT(unsigned width, unsigned height)
{
if (!width || !height)
return false;
if ((width & (width - 1)) || (height & (height - 1)))
return true;
return false;
}
void WebGLTexture::_deleteObject(Platform3DObject object)
{
context()->graphicsContext3D()->deleteTexture(object);
}
void WebGLTexture::updateNPOTStates()
{
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)) {
m_isNPOT = false;
break;
}
if (isNPOT(m_width[ii], m_height[ii]))
m_isNPOT = true;
}
m_needToUseBlackTexture = false;
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;
}
}
#endif // ENABLE(3D_CANVAS)