Implements generateMipmap for CPU-side textures
TRAC #22350
Author: Shannon Woods
Signed-off-by: Jamie Madill
Signed-off-by: Daniel Koch
git-svn-id: https://angleproject.googlecode.com/svn/branches/dx11proto@1763 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libGLESv2/renderer/Image11.cpp b/src/libGLESv2/renderer/Image11.cpp
index 92e186c..a8a703b 100644
--- a/src/libGLESv2/renderer/Image11.cpp
+++ b/src/libGLESv2/renderer/Image11.cpp
@@ -15,6 +15,7 @@
#include "libGLESv2/main.h"
#include "libGLESv2/mathutil.h"
#include "libGLESv2/renderer/renderer11_utils.h"
+#include "libGLESv2/renderer/generatemip.h"
namespace rx
{
@@ -40,6 +41,69 @@
return static_cast<rx::Image11*>(img);
}
+void Image11::generateMipmap(Image11 *dest, Image11 *src)
+{
+ ASSERT(src->getDXGIFormat() == dest->getDXGIFormat());
+ ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth());
+ ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
+
+ D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped;
+ dest->map(&destMapped);
+ src->map(&srcMapped);
+
+ const unsigned char *sourceData = reinterpret_cast<const unsigned char*>(srcMapped.pData);
+ unsigned char *destData = reinterpret_cast<unsigned char*>(destMapped.pData);
+
+ if (sourceData && destData)
+ {
+ switch (src->getDXGIFormat())
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ GenerateMip<R8G8B8A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_A8_UNORM:
+ GenerateMip<A8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R8_UNORM:
+ GenerateMip<R8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ GenerateMip<A32B32G32R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ GenerateMip<R32G32B32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ GenerateMip<A16B16G16R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R8G8_UNORM:
+ GenerateMip<R8G8>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R16_FLOAT:
+ GenerateMip<R16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R16G16_FLOAT:
+ GenerateMip<R16G16F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R32_FLOAT:
+ GenerateMip<R32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ case DXGI_FORMAT_R32G32_FLOAT:
+ GenerateMip<R32G32F>(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ dest->unmap();
+ src->unmap();
+ }
+
+ dest->markDirty();
+}
+
bool Image11::isDirty() const
{
return (mStagingTexture && mDirty);
diff --git a/src/libGLESv2/renderer/Image11.h b/src/libGLESv2/renderer/Image11.h
index 159df5b..7693aa5 100644
--- a/src/libGLESv2/renderer/Image11.h
+++ b/src/libGLESv2/renderer/Image11.h
@@ -36,6 +36,8 @@
static Image11 *makeImage11(Image *img);
+ static void generateMipmap(Image11 *dest, Image11 *src);
+
virtual bool isDirty() const;
ID3D11Texture2D *getStagingTexture();
@@ -54,15 +56,16 @@
virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
+ protected:
+ HRESULT map(D3D11_MAPPED_SUBRESOURCE *map);
+ void unmap();
+
private:
DISALLOW_COPY_AND_ASSIGN(Image11);
void createStagingTexture();
bool updateStagingTexture(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
- HRESULT map(D3D11_MAPPED_SUBRESOURCE *map);
- void unmap();
-
Renderer11 *mRenderer;
DXGI_FORMAT mDXGIFormat;
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 1d0731a..c43ce6e 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -2414,9 +2414,9 @@
void Renderer11::generateMipmap(Image *dest, Image *src)
{
- // TODO
- UNIMPLEMENTED();
- return;
+ Image11 *dest11 = Image11::makeImage11(dest);
+ Image11 *src11 = Image11::makeImage11(src);
+ Image11::generateMipmap(dest11, src11);
}
TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
diff --git a/src/libGLESv2/renderer/generatemip.h b/src/libGLESv2/renderer/generatemip.h
index 988adc0..8e19736 100644
--- a/src/libGLESv2/renderer/generatemip.h
+++ b/src/libGLESv2/renderer/generatemip.h
@@ -24,6 +24,9 @@
}
};
+typedef L8 R8; // R8 type is functionally equivalent for mip purposes
+typedef L8 A8; // A8 type is functionally equivalent for mip purposes
+
struct A8L8
{
unsigned char L;
@@ -35,6 +38,8 @@
}
};
+typedef A8L8 R8G8; // R8G8 type is functionally equivalent for mip purposes
+
struct A8R8G8B8
{
unsigned char B;
@@ -48,6 +53,8 @@
}
};
+typedef A8R8G8B8 R8G8B8A8; // R8G8B8A8 type is functionally equivalent for mip purposes
+
struct A16B16G16R16F
{
unsigned short R;
@@ -64,6 +71,28 @@
}
};
+struct R16F
+{
+ unsigned short R;
+
+ static void average(R16F *dst, const R16F *src1, const R16F *src2)
+ {
+ dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
+ }
+};
+
+struct R16G16F
+{
+ unsigned short R;
+ unsigned short G;
+
+ static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2)
+ {
+ dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f);
+ dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f);
+ }
+};
+
struct A32B32G32R32F
{
float R;
@@ -80,6 +109,42 @@
}
};
+struct R32F
+{
+ float R;
+
+ static void average(R32F *dst, const R32F *src1, const R32F *src2)
+ {
+ dst->R = (src1->R + src2->R) * 0.5f;
+ }
+};
+
+struct R32G32F
+{
+ float R;
+ float G;
+
+ static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2)
+ {
+ dst->R = (src1->R + src2->R) * 0.5f;
+ dst->G = (src1->G + src2->G) * 0.5f;
+ }
+};
+
+struct R32G32B32F
+{
+ float R;
+ float G;
+ float B;
+
+ static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2)
+ {
+ dst->R = (src1->R + src2->R) * 0.5f;
+ dst->G = (src1->G + src2->G) * 0.5f;
+ dst->B = (src1->B + src2->B) * 0.5f;
+ }
+};
+
template <typename T>
static void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight,
const unsigned char *sourceData, int sourcePitch,