return true;\r
}\r
\r
+ bool Device::stretchCube(egl::Image *source, egl::Image *dest)\r
+ {\r
+ if(!source || !dest || Image::isDepth(source->getInternalFormat()) || Image::isStencil(source->getInternalFormat()))\r
+ {\r
+ ERR("Invalid parameters");\r
+ return false;\r
+ }\r
+\r
+ int sWidth = source->getExternalWidth();\r
+ int sHeight = source->getExternalHeight();\r
+ int sDepth = source->getExternalDepth();\r
+ int dWidth = dest->getExternalWidth();\r
+ int dHeight = dest->getExternalHeight();\r
+ int dDepth = dest->getExternalDepth();\r
+\r
+ bool scaling = (sWidth != dWidth) || (sHeight != dHeight) || (sDepth != dDepth);\r
+ bool equalFormats = source->getInternalFormat() == dest->getInternalFormat();\r
+ bool alpha0xFF = false;\r
+\r
+ if((source->getInternalFormat() == FORMAT_A8R8G8B8 && dest->getInternalFormat() == FORMAT_X8R8G8B8) ||\r
+ (source->getInternalFormat() == FORMAT_X8R8G8B8 && dest->getInternalFormat() == FORMAT_A8R8G8B8))\r
+ {\r
+ equalFormats = true;\r
+ alpha0xFF = true;\r
+ }\r
+\r
+ if(!scaling && equalFormats)\r
+ {\r
+ unsigned int sourcePitch = source->getInternalPitchB();\r
+ unsigned int destPitch = dest->getInternalPitchB();\r
+ unsigned int bytes = dWidth * Image::bytes(source->getInternalFormat());\r
+\r
+ for(int z = 0; z < dDepth; ++z)\r
+ {\r
+ unsigned char *sourceBytes = (unsigned char*)source->lockInternal(0, 0, z, LOCK_READONLY, PUBLIC);\r
+ unsigned char *destBytes = (unsigned char*)dest->lockInternal(0, 0, z, LOCK_READWRITE, PUBLIC);\r
+ for(int y = 0; y < dHeight; ++y)\r
+ {\r
+ memcpy(destBytes, sourceBytes, bytes);\r
+\r
+ if(alpha0xFF)\r
+ {\r
+ for(int x = 0; x < dWidth; ++x)\r
+ {\r
+ destBytes[4 * x + 3] = 0xFF;\r
+ }\r
+ }\r
+\r
+ sourceBytes += sourcePitch;\r
+ destBytes += destPitch;\r
+ }\r
+ }\r
+\r
+ source->unlockInternal();\r
+ dest->unlockInternal();\r
+ }\r
+ else\r
+ {\r
+ blit3D(source, dest);\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
bool Device::bindResources()\r
{\r
if(!bindViewport())\r
virtual void setViewport(const Viewport &viewport);\r
\r
virtual bool stretchRect(egl::Image *sourceSurface, const sw::SliceRect *sourceRect, egl::Image *destSurface, const sw::SliceRect *destRect, bool filter);\r
+ virtual bool stretchCube(egl::Image *sourceSurface, egl::Image *destSurface);\r
virtual void finish();\r
\r
private:\r
\r
void Texture3D::generateMipmaps()\r
{\r
- UNIMPLEMENTED();\r
+ if(!image[0])\r
+ {\r
+ return; // FIXME: error?\r
+ }\r
+\r
+ unsigned int q = log2(std::max(std::max(image[0]->getWidth(), image[0]->getHeight()), image[0]->getDepth()));\r
+\r
+ for(unsigned int i = 1; i <= q; i++)\r
+ {\r
+ if(image[i])\r
+ {\r
+ image[i]->unbind(this);\r
+ }\r
+\r
+ image[i] = new Image(this, std::max(image[0]->getWidth() >> i, 1), std::max(image[0]->getHeight() >> i, 1), std::max(image[0]->getDepth() >> i, 1), image[0]->getFormat(), image[0]->getType());\r
+\r
+ if(!image[i])\r
+ {\r
+ return error(GL_OUT_OF_MEMORY);\r
+ }\r
+\r
+ getDevice()->stretchCube(image[i - 1], image[i]);\r
+ }\r
}\r
\r
egl::Image *Texture3D::getImage(unsigned int level)\r
source->lockInternal(sRect.x0, sRect.y0, sRect.slice, sw::LOCK_READONLY, sw::PUBLIC);
dest->lockInternal(dRect.x0, dRect.y0, dRect.slice, sw::LOCK_WRITEONLY, sw::PUBLIC);
- float w = 1.0f / (dRect.x1 - dRect.x0) * (sRect.x1 - sRect.x0);
- float h = 1.0f / (dRect.y1 - dRect.y0) * (sRect.y1 - sRect.y0);
+ float w = static_cast<float>(sRect.x1 - sRect.x0) / static_cast<float>(dRect.x1 - dRect.x0);
+ float h = static_cast<float>(sRect.y1 - sRect.y0) / static_cast<float>(dRect.y1 - dRect.y0);
const float xStart = (float)sRect.x0 + 0.5f * w;
float y = (float)sRect.y0 + 0.5f * h;
dest->unlockInternal();
}
+ void Blitter::blit3D(Surface *source, Surface *dest)
+ {
+ source->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
+ dest->lockInternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PUBLIC);
+
+ float w = static_cast<float>(source->getExternalWidth()) / static_cast<float>(dest->getExternalWidth());
+ float h = static_cast<float>(source->getExternalHeight()) / static_cast<float>(dest->getExternalHeight());
+ float d = static_cast<float>(source->getExternalDepth()) / static_cast<float>(dest->getExternalDepth());
+
+ float z = 0.5f * d;
+ for(int k = 0; k < dest->getExternalDepth(); ++k)
+ {
+ float y = 0.5f * h;
+ for(int j = 0; j < dest->getExternalHeight(); ++j)
+ {
+ float x = 0.5f * w;
+ for(int i = 0; i < dest->getExternalWidth(); ++i)
+ {
+ dest->writeInternal(i, j, k, source->sampleInternal(x, y, z));
+ x += w;
+ }
+ y += h;
+ }
+ z += d;
+ }
+
+ source->unlockInternal();
+ dest->unlockInternal();
+ }
+
bool Blitter::read(Float4 &c, Pointer<Byte> element, Format format)
{
c = Float4(1.0f, 1.0f, 1.0f, 1.0f);
virtual ~Blitter();\r
\r
void blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter);\r
+ void blit3D(Surface *source, Surface *dest);\r
\r
private:\r
bool read(Float4 &color, Pointer<Byte> element, Format format);\r
blitter.blit(source, sRect, dest, dRect, filter);
}
+ void Renderer::blit3D(Surface *source, Surface *dest)
+ {
+ blitter.blit3D(source, dest);
+ }
+
void Renderer::draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update)
{
#ifndef NDEBUG
virtual ~Renderer();
virtual void blit(Surface *source, const SliceRect &sRect, Surface *dest, const SliceRect &dRect, bool filter);
+ virtual void blit3D(Surface *source, Surface *dest);
virtual void draw(DrawType drawType, unsigned int indexOffset, unsigned int count, bool update = true);
virtual void setIndexBuffer(Resource *indexBuffer);