Commit 9616e583 by apatrick@chromium.org

Merge no-flip-rows r1142 to trunk.

Review URL: https://codereview.appspot.com/6304052 git-svn-id: https://angleproject.googlecode.com/svn/trunk@1162 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent e6357c0e
#define MAJOR_VERSION 1
#define MINOR_VERSION 0
#define BUILD_VERSION 0
#define BUILD_REVISION 1156
#define BUILD_REVISION 1162
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
......
......@@ -219,25 +219,11 @@ void OutputHLSL::header()
out << uniforms;
out << "\n";
// The texture fetch functions "flip" the Y coordinate in one way or another. This is because textures are stored
// according to the OpenGL convention, i.e. (0, 0) is "bottom left", rather than the D3D convention where (0, 0)
// is "top left". Since the HLSL texture fetch functions expect textures to be stored according to the D3D
// convention, the Y coordinate passed to these functions is adjusted to compensate.
//
// The simplest case is texture2D where the mapping is Y -> 1-Y, which maps [0, 1] -> [1, 0].
//
// The texture2DProj functions are more complicated because the projection divides by either Z or W. For the vec3
// case, the mapping is Y -> Z-Y or Y/Z -> 1-Y/Z, which again maps [0, 1] -> [1, 0].
//
// For cube textures the mapping is Y -> -Y, which maps [-1, 1] -> [1, -1]. This is not sufficient on its own for the
// +Y and -Y faces, which are now on the "wrong sides" of the cube. This is compensated for by exchanging the
// +Y and -Y faces everywhere else throughout the code.
if (mUsesTexture2D)
{
out << "float4 gl_texture2D(sampler2D s, float2 t)\n"
"{\n"
" return tex2D(s, float2(t.x, 1 - t.y));\n"
" return tex2D(s, t);\n"
"}\n"
"\n";
}
......@@ -246,7 +232,7 @@ void OutputHLSL::header()
{
out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n"
"{\n"
" return tex2Dbias(s, float4(t.x, 1 - t.y, 0, bias));\n"
" return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n"
"}\n"
"\n";
}
......@@ -255,12 +241,12 @@ void OutputHLSL::header()
{
out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n"
"{\n"
" return tex2Dproj(s, float4(t.x, t.z - t.y, 0, t.z));\n"
" return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n"
"}\n"
"\n"
"float4 gl_texture2DProj(sampler2D s, float4 t)\n"
"{\n"
" return tex2Dproj(s, float4(t.x, t.w - t.y, t.z, t.w));\n"
" return tex2Dproj(s, t);\n"
"}\n"
"\n";
}
......@@ -269,12 +255,12 @@ void OutputHLSL::header()
{
out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n"
"{\n"
" return tex2Dbias(s, float4(t.x / t.z, 1 - (t.y / t.z), 0, bias));\n"
" return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n"
"}\n"
"\n"
"float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n"
"{\n"
" return tex2Dbias(s, float4(t.x / t.w, 1 - (t.y / t.w), 0, bias));\n"
" return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n"
"}\n"
"\n";
}
......@@ -283,7 +269,7 @@ void OutputHLSL::header()
{
out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n"
"{\n"
" return texCUBE(s, float3(t.x, -t.y, t.z));\n"
" return texCUBE(s, t);\n"
"}\n"
"\n";
}
......@@ -292,7 +278,7 @@ void OutputHLSL::header()
{
out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n"
"{\n"
" return texCUBEbias(s, float4(t.x, -t.y, t.z, bias));\n"
" return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n"
"}\n"
"\n";
}
......@@ -303,7 +289,7 @@ void OutputHLSL::header()
{
out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n"
"{\n"
" return tex2Dlod(s, float4(t.x, 1 - t.y, 0, 0));\n"
" return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
"}\n"
"\n";
}
......@@ -312,7 +298,7 @@ void OutputHLSL::header()
{
out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n"
"{\n"
" return tex2Dlod(s, float4(t.x, 1 - t.y, 0, 0));\n"
" return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n"
"}\n"
"\n";
}
......@@ -321,12 +307,12 @@ void OutputHLSL::header()
{
out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n"
"{\n"
" return tex2Dlod(s, float4(t.x / t.z, 1 - t.y / t.z, 0, 0));\n"
" return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
"}\n"
"\n"
"float4 gl_texture2DProjLod(sampler2D s, float4 t)\n"
"{\n"
" return tex2Dlod(s, float4(t.x / t.w, 1 - t.y / t.w, 0, 0));\n"
" return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
"}\n"
"\n";
}
......@@ -335,12 +321,12 @@ void OutputHLSL::header()
{
out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n"
"{\n"
" return tex2Dlod(s, float4(t.x / t.z, 1 - t.y / t.z, 0, 0));\n"
" return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n"
"}\n"
"\n"
"float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n"
"{\n"
" return tex2Dlod(s, float4(t.x / t.w, 1 - t.y / t.w, 0, 0));\n"
" return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n"
"}\n"
"\n";
}
......@@ -349,7 +335,7 @@ void OutputHLSL::header()
{
out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n"
"{\n"
" return texCUBElod(s, float4(t.x, -t.y, t.z, 0));\n"
" return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
"}\n"
"\n";
}
......@@ -358,7 +344,7 @@ void OutputHLSL::header()
{
out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n"
"{\n"
" return texCUBElod(s, float4(t.x, -t.y, t.z, 0));\n"
" return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n"
"}\n"
"\n";
}
......@@ -1232,7 +1218,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
}
else
{
outputTriplet(visit, "(-ddy(", "", "))");
outputTriplet(visit, "ddy(", "", ")");
}
break;
case EOpFwidth:
......
......@@ -43,6 +43,7 @@ Surface::Surface(Display *display, const Config *config, HWND window, EGLint pos
: mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported)
{
mSwapChain = NULL;
mBackBuffer = NULL;
mDepthStencil = NULL;
mRenderTarget = NULL;
mOffscreenTexture = NULL;
......@@ -64,6 +65,7 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL
: mDisplay(display), mWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
{
mSwapChain = NULL;
mBackBuffer = NULL;
mDepthStencil = NULL;
mRenderTarget = NULL;
mOffscreenTexture = NULL;
......@@ -121,6 +123,12 @@ void Surface::release()
mSwapChain = NULL;
}
if (mBackBuffer)
{
mBackBuffer->Release();
mBackBuffer = NULL;
}
if (mDepthStencil)
{
mDepthStencil->Release();
......@@ -144,6 +152,8 @@ void Surface::release()
mTexture->releaseTexImage();
mTexture = NULL;
}
mShareHandle = NULL;
}
bool Surface::resetSwapChain()
......@@ -174,57 +184,13 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
return false;
}
IDirect3DSurface9* preservedRenderTarget = NULL;
if (mPostSubBufferSupported && mRenderTarget)
{
preservedRenderTarget = mRenderTarget;
preservedRenderTarget->AddRef();
}
// Evict all non-render target textures to system memory and release all resources
// before reallocating them to free up as much video memory as possible.
device->EvictManagedResources();
release();
D3DPRESENT_PARAMETERS presentParameters = {0};
HRESULT result;
bool useFlipEx = (getComparableOSVersion() >= versionWindows7) && mDisplay->isD3d9ExDevice();
// FlipEx causes unseemly stretching when resizing windows AND when one
// draws outside of the WM_PAINT callback. While this is seldom a problem in
// single process applications, it is particuarly noticeable in multiprocess
// applications. Therefore, if the creator process of our window is not in
// the current process, disable use of FlipEx.
DWORD windowPID;
GetWindowThreadProcessId(mWindow, &windowPID);
if (windowPID != GetCurrentProcessId())
{
useFlipEx = false;
}
// Various hardware does not support D3DSWAPEFFECT_FLIPEX when either the
// device format or back buffer format is not 32-bit.
HDC deviceContext = GetDC(0);
int deviceFormatBits = GetDeviceCaps(deviceContext, BITSPIXEL);
ReleaseDC(0, deviceContext);
if (mConfig->mBufferSize != 32 || deviceFormatBits != 32)
{
useFlipEx = false;
}
// D3DSWAPEFFECT_FLIPEX is always VSYNCed
if (mSwapInterval == 0)
{
useFlipEx = false;
}
// D3DSWAPEFFECT_FLIPEX does not preserve the back buffer.
if (mPostSubBufferSupported)
{
useFlipEx = false;
}
presentParameters.AutoDepthStencilFormat = mConfig->mDepthStencilFormat;
// We set BackBufferCount = 1 even when we use D3DSWAPEFFECT_FLIPEX.
// We do this because DirectX docs are a bit vague whether to set this to 1
......@@ -239,42 +205,51 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
presentParameters.PresentationInterval = mPresentInterval;
// Use flipEx on Win7 or greater.
if(useFlipEx)
presentParameters.SwapEffect = D3DSWAPEFFECT_FLIPEX;
else
presentParameters.SwapEffect = mPostSubBufferSupported ? D3DSWAPEFFECT_COPY : D3DSWAPEFFECT_DISCARD;
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.Windowed = TRUE;
presentParameters.BackBufferWidth = backbufferWidth;
presentParameters.BackBufferHeight = backbufferHeight;
if (mWindow)
// Release specific resources to free up memory for the new render target, while the
// old render target still exists for the purpose of preserving its contents.
if (mSwapChain)
{
result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
} else {
HANDLE *pShareHandle = NULL;
if (mDisplay->shareHandleSupported()) {
pShareHandle = &mShareHandle;
mSwapChain->Release();
mSwapChain = NULL;
}
result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
if (mBackBuffer)
{
mBackBuffer->Release();
mBackBuffer = NULL;
}
if (FAILED(result))
if (mOffscreenTexture)
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
release();
mOffscreenTexture->Release();
mOffscreenTexture = NULL;
}
if (mDepthStencil)
{
mDepthStencil->Release();
mDepthStencil = NULL;
}
if (preservedRenderTarget)
mShareHandle = NULL;
HANDLE *pShareHandle = NULL;
if (!mWindow && mDisplay->shareHandleSupported())
{
preservedRenderTarget->Release();
preservedRenderTarget = NULL;
pShareHandle = &mShareHandle;
}
result = device->CreateTexture(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight, 1, D3DUSAGE_RENDERTARGET,
presentParameters.BackBufferFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle);
if (FAILED(result))
{
ERR("Could not create offscreen texture: %08lX", result);
release();
if(isDeviceLostError(result))
{
mDisplay->notifyDeviceLost();
......@@ -286,20 +261,12 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
}
}
if (mWindow)
{
mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mRenderTarget);
if (!preservedRenderTarget)
{
InvalidateRect(mWindow, NULL, FALSE);
}
}
else
{
mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
}
IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
if (preservedRenderTarget)
result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
ASSERT(SUCCEEDED(result));
if (oldRenderTarget)
{
RECT rect =
{
......@@ -318,10 +285,37 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
}
mDisplay->endScene();
device->StretchRect(preservedRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
preservedRenderTarget->Release();
preservedRenderTarget = NULL;
result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
ASSERT(SUCCEEDED(result));
oldRenderTarget->Release();
}
if (mWindow)
{
result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result);
release();
if(isDeviceLostError(result))
{
mDisplay->notifyDeviceLost();
return false;
}
else
{
return error(EGL_BAD_ALLOC, false);
}
}
result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
ASSERT(SUCCEEDED(result));
}
if (mConfig->mDepthStencilFormat != D3DFMT_UNKNOWN)
......@@ -329,7 +323,6 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
result = device->CreateDepthStencilSurface(presentParameters.BackBufferWidth, presentParameters.BackBufferHeight,
presentParameters.AutoDepthStencilFormat, presentParameters.MultiSampleType,
presentParameters.MultiSampleQuality, FALSE, &mDepthStencil, NULL);
}
if (FAILED(result))
{
......@@ -337,8 +330,18 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
release();
if(isDeviceLostError(result))
{
mDisplay->notifyDeviceLost();
return false;
}
else
{
return error(EGL_BAD_ALLOC, false);
}
}
}
mWidth = presentParameters.BackBufferWidth;
mHeight = presentParameters.BackBufferHeight;
......@@ -347,6 +350,113 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
return true;
}
bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
{
if (!mSwapChain)
{
return true;
}
if (x + width > mWidth)
{
width = mWidth - x;
}
if (y + height > mHeight)
{
height = mHeight - y;
}
if (width == 0 || height == 0)
{
return true;
}
IDirect3DDevice9 *device = mDisplay->getDevice();
// Disable all pipeline operations
device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
device->SetPixelShader(NULL);
device->SetVertexShader(NULL);
device->SetRenderTarget(0, mBackBuffer);
device->SetDepthStencilSurface(NULL);
device->SetTexture(0, mOffscreenTexture);
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f};
device->SetViewport(&viewport);
float x1 = x - 0.5f;
float y1 = (mHeight - y - height) - 0.5f;
float x2 = (x + width) - 0.5f;
float y2 = (mHeight - y) - 0.5f;
float u1 = x / float(mWidth);
float v1 = y / float(mHeight);
float u2 = (x + width) / float(mWidth);
float v2 = (y + height) / float(mHeight);
float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
{x2, y1, 0.0f, 1.0f, u2, v2},
{x2, y2, 0.0f, 1.0f, u2, v1},
{x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v
mDisplay->startScene();
device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
mDisplay->endScene();
device->SetTexture(0, NULL);
RECT rect =
{
x, mHeight - y - height,
x + width, mHeight - y
};
HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
gl::Context *context = static_cast<gl::Context*>(glGetCurrentContext());
if (context)
{
context->markAllStateDirty();
}
if (isDeviceLostError(result))
{
mDisplay->notifyDeviceLost();
return false;
}
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
{
return error(EGL_BAD_ALLOC, false);
}
ASSERT(SUCCEEDED(result));
checkForOutOfDateSwapChain();
return true;
}
HWND Surface::getWindowHandle()
{
return mWindow;
......@@ -467,87 +577,18 @@ DWORD Surface::convertInterval(EGLint interval)
bool Surface::swap()
{
if (mSwapChain)
{
mDisplay->endScene();
HRESULT result = mSwapChain->Present(NULL, NULL, NULL, NULL, 0);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
{
return error(EGL_BAD_ALLOC, false);
}
if (isDeviceLostError(result))
{
mDisplay->notifyDeviceLost();
return false;
}
ASSERT(SUCCEEDED(result));
checkForOutOfDateSwapChain();
}
return true;
return swapRect(0, 0, mWidth, mHeight);
}
bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{
if (x < 0 || y < 0 || width < 0 || height < 0)
{
return error(EGL_BAD_PARAMETER, false);
}
if (!mPostSubBufferSupported)
{
// Spec is not clear about how this should be handled.
return true;
}
if (mSwapChain)
{
mDisplay->endScene();
RECT rect =
{
x, mHeight - y - height,
x + width, mHeight - y
};
if (rect.right > mWidth)
{
rect.right = mWidth;
}
if (rect.bottom > mHeight)
{
rect.bottom = mHeight;
}
if (rect.left == rect.right || rect.top == rect.bottom)
{
return true;
}
HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR)
{
return error(EGL_BAD_ALLOC, false);
}
if (result == D3DERR_DEVICELOST || result == D3DERR_DEVICEHUNG || result == D3DERR_DEVICEREMOVED)
{
return error(EGL_CONTEXT_LOST, false);
}
ASSERT(SUCCEEDED(result));
checkForOutOfDateSwapChain();
}
return true;
return swapRect(x, y, width, height);
}
EGLint Surface::getWidth() const
......
......@@ -69,6 +69,7 @@ private:
Display *const mDisplay;
IDirect3DSwapChain9 *mSwapChain;
IDirect3DSurface9 *mBackBuffer;
IDirect3DSurface9 *mDepthStencil;
IDirect3DSurface9* mRenderTarget;
IDirect3DTexture9* mOffscreenTexture;
......@@ -78,6 +79,7 @@ private:
void subclassWindow();
void unsubclassWindow();
bool resetSwapChain(int backbufferWidth, int backbufferHeight);
bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
static DWORD convertInterval(EGLint interval);
const HWND mWindow; // Window that the surface is created for.
......
......@@ -1108,6 +1108,11 @@ EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLi
try
{
if (x < 0 || y < 0 || width < 0 || height < 0)
{
return error(EGL_BAD_PARAMETER, EGL_FALSE);
}
egl::Display *display = static_cast<egl::Display*>(dpy);
egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
......
......@@ -1955,11 +1955,10 @@ bool Context::applyRenderTarget(bool ignoreViewport)
}
else
{
RECT rect = transformPixelRect(mState.viewportX, mState.viewportY, mState.viewportWidth, mState.viewportHeight, mRenderTargetDesc.Height);
viewport.X = clamp(rect.left, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
viewport.Y = clamp(rect.top, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
viewport.Width = clamp(rect.right - rect.left, 0L, static_cast<LONG>(mRenderTargetDesc.Width) - static_cast<LONG>(viewport.X));
viewport.Height = clamp(rect.bottom - rect.top, 0L, static_cast<LONG>(mRenderTargetDesc.Height) - static_cast<LONG>(viewport.Y));
viewport.X = clamp(mState.viewportX, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
viewport.Y = clamp(mState.viewportY, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
viewport.Width = clamp(mState.viewportWidth, 0L, static_cast<LONG>(mRenderTargetDesc.Width) - static_cast<LONG>(viewport.X));
viewport.Height = clamp(mState.viewportHeight, 0L, static_cast<LONG>(mRenderTargetDesc.Height) - static_cast<LONG>(viewport.Y));
viewport.MinZ = zNear;
viewport.MaxZ = zFar;
}
......@@ -1981,11 +1980,11 @@ bool Context::applyRenderTarget(bool ignoreViewport)
{
if (mState.scissorTest)
{
RECT rect = transformPixelRect(mState.scissorX, mState.scissorY, mState.scissorWidth, mState.scissorHeight, mRenderTargetDesc.Height);
rect.left = clamp(rect.left, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
rect.top = clamp(rect.top, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
rect.right = clamp(rect.right, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
rect.bottom = clamp(rect.bottom, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
RECT rect;
rect.left = clamp(mState.scissorX, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
rect.top = clamp(mState.scissorY, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
rect.right = clamp(mState.scissorX + mState.scissorWidth, 0L, static_cast<LONG>(mRenderTargetDesc.Width));
rect.bottom = clamp(mState.scissorY + mState.scissorHeight, 0L, static_cast<LONG>(mRenderTargetDesc.Height));
mDevice->SetScissorRect(&rect);
mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
}
......@@ -2006,10 +2005,9 @@ bool Context::applyRenderTarget(bool ignoreViewport)
GLfloat xy[2] = {1.0f / viewport.Width, -1.0f / viewport.Height};
programBinary->setUniform2fv(halfPixelSize, 1, xy);
// These values are used for computing gl_FragCoord in Program::linkVaryings(). The approach depends on Shader Model 3.0 support.
// These values are used for computing gl_FragCoord in Program::linkVaryings().
GLint coord = programBinary->getDxCoordLocation();
float h = mSupportsShaderModel3 ? mRenderTargetDesc.Height : mState.viewportHeight / 2.0f;
GLfloat whxy[4] = {mState.viewportWidth / 2.0f, h,
GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
(float)mState.viewportX + mState.viewportWidth / 2.0f,
(float)mState.viewportY + mState.viewportHeight / 2.0f};
programBinary->setUniform4fv(coord, 1, whxy);
......@@ -2035,10 +2033,8 @@ void Context::applyState(GLenum drawMode)
Framebuffer *framebufferObject = getDrawFramebuffer();
GLenum adjustedFrontFace = adjustWinding(mState.frontFace);
GLint frontCCW = programBinary->getDxFrontCCWLocation();
GLint ccw = (adjustedFrontFace == GL_CCW);
GLint ccw = (mState.frontFace == GL_CCW);
programBinary->setUniform1iv(frontCCW, 1, &ccw);
GLint pointsOrLines = programBinary->getDxPointsOrLinesLocation();
......@@ -2057,7 +2053,7 @@ void Context::applyState(GLenum drawMode)
{
if (mState.cullFace)
{
mDevice->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, adjustedFrontFace));
mDevice->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
}
else
{
......@@ -2157,32 +2153,32 @@ void Context::applyState(GLenum drawMode)
gl::Renderbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
es2dx::ConvertComparison(mState.stencilFunc));
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
es2dx::ConvertStencilOp(mState.stencilFail));
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
mDevice->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
mDevice->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
es2dx::ConvertComparison(mState.stencilBackFunc));
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
es2dx::ConvertStencilOp(mState.stencilBackFail));
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
mDevice->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
mDevice->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
}
else
......@@ -2475,7 +2471,7 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
HRESULT result;
IDirect3DSurface9 *systemSurface = NULL;
bool directToPixels = getPackReverseRowOrder() && getPackAlignment() <= 4 && mDisplay->isD3d9ExDevice() &&
bool directToPixels = !getPackReverseRowOrder() && getPackAlignment() <= 4 && mDisplay->isD3d9ExDevice() &&
x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height &&
desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
if (directToPixels)
......@@ -2528,13 +2524,13 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
return;
}
D3DLOCKED_RECT lock;
RECT rect = transformPixelRect(x, y, width, height, desc.Height);
rect.left = clamp(rect.left, 0L, static_cast<LONG>(desc.Width));
rect.top = clamp(rect.top, 0L, static_cast<LONG>(desc.Height));
rect.right = clamp(rect.right, 0L, static_cast<LONG>(desc.Width));
rect.bottom = clamp(rect.bottom, 0L, static_cast<LONG>(desc.Height));
RECT rect;
rect.left = clamp(x, 0L, static_cast<LONG>(desc.Width));
rect.top = clamp(y, 0L, static_cast<LONG>(desc.Height));
rect.right = clamp(x + width, 0L, static_cast<LONG>(desc.Width));
rect.bottom = clamp(y + height, 0L, static_cast<LONG>(desc.Height));
D3DLOCKED_RECT lock;
result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
if (FAILED(result))
......@@ -2552,13 +2548,13 @@ void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
int inputPitch;
if (getPackReverseRowOrder())
{
source = (unsigned char*)lock.pBits;
inputPitch = lock.Pitch;
source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
inputPitch = -lock.Pitch;
}
else
{
source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
inputPitch = -lock.Pitch;
source = (unsigned char*)lock.pBits;
inputPitch = lock.Pitch;
}
for (int j = 0; j < rect.bottom - rect.top; j++)
......@@ -3879,17 +3875,17 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
if (srcY0 < srcY1)
{
sourceRect.top = readBufferHeight - srcY1;
destRect.top = drawBufferHeight - dstY1;
sourceRect.bottom = readBufferHeight - srcY0;
destRect.bottom = drawBufferHeight - dstY0;
sourceRect.bottom = srcY1;
destRect.bottom = dstY1;
sourceRect.top = srcY0;
destRect.top = dstY0;
}
else
{
sourceRect.top = readBufferHeight - srcY0;
destRect.top = drawBufferHeight - dstY0;
sourceRect.bottom = readBufferHeight - srcY1;
destRect.bottom = drawBufferHeight - dstY1;
sourceRect.bottom = srcY0;
destRect.bottom = dstY0;
sourceRect.top = srcY1;
destRect.top = dstY1;
}
RECT sourceScissoredRect = sourceRect;
......
......@@ -281,7 +281,7 @@ class Context
void makeCurrent(egl::Display *display, egl::Surface *surface);
void markAllStateDirty();
virtual void markAllStateDirty();
void markDxUniformsDirty();
virtual void markContextLost();
......
......@@ -1391,7 +1391,7 @@ bool ProgramBinary::linkVaryings(std::string& pixelHLSL, std::string& vertexHLSL
"\n"
" VS_OUTPUT output;\n"
" output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
" output.gl_Position.y = gl_Position.y - dx_HalfPixelSize.y * gl_Position.w;\n"
" output.gl_Position.y = -(gl_Position.y + dx_HalfPixelSize.y * gl_Position.w);\n"
" output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output.gl_Position.w = gl_Position.w;\n";
......@@ -1524,15 +1524,14 @@ bool ProgramBinary::linkVaryings(std::string& pixelHLSL, std::string& vertexHLSL
if (sm3)
{
// dx_Coord.y contains the render target height. See Context::applyRenderTarget()
pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
" gl_FragCoord.y = dx_Coord.y - input.dx_VPos.y - 0.5;\n";
" gl_FragCoord.y = input.dx_VPos.y + 0.5;\n";
}
else
{
// dx_Coord contains the viewport width/2, height/2, center.x and center.y. See Context::applyRenderTarget()
pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Coord.x + dx_Coord.z;\n"
" gl_FragCoord.y = -(input.gl_FragCoord.y * rhw) * dx_Coord.y + dx_Coord.w;\n";
" gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Coord.y + dx_Coord.w;\n";
}
pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
......@@ -1541,7 +1540,8 @@ bool ProgramBinary::linkVaryings(std::string& pixelHLSL, std::string& vertexHLSL
if (fragmentShader->mUsesPointCoord && sm3)
{
pixelHLSL += " gl_PointCoord = input.gl_PointCoord;\n";
pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n";
pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
}
if (fragmentShader->mUsesFrontFacing)
......
......@@ -291,7 +291,11 @@ void Image::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint y
if (sourceSurface && sourceSurface != destSurface)
{
RECT rect = transformPixelRect(xoffset, yoffset, width, height, mHeight);
RECT rect;
rect.left = xoffset;
rect.top = yoffset;
rect.right = xoffset + width;
rect.bottom = yoffset + height;
if (mD3DPool == D3DPOOL_MANAGED)
{
......@@ -309,11 +313,15 @@ void Image::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint y
}
// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
// into the target pixel rectangle at locked.pBits with locked.Pitch bytes in between each line.
// into the target pixel rectangle.
void Image::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum type,
GLint unpackAlignment, const void *input)
{
RECT lockRect = transformPixelRect(xoffset, yoffset, width, height, mHeight);
RECT lockRect =
{
xoffset, yoffset,
xoffset + width, yoffset + height
};
D3DLOCKED_RECT locked;
HRESULT result = lock(&locked, &lockRect);
......@@ -322,8 +330,7 @@ void Image::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height
return;
}
GLsizei inputPitch = -ComputePitch(width, mFormat, type, unpackAlignment);
input = ((char*)input) - inputPitch * (height - 1);
GLsizei inputPitch = ComputePitch(width, mFormat, type, unpackAlignment);
switch (type)
{
......@@ -908,7 +915,10 @@ void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsi
ASSERT(xoffset % 4 == 0);
ASSERT(yoffset % 4 == 0);
RECT lockRect = transformPixelRect(xoffset, yoffset, width, height, mHeight);
RECT lockRect = {
xoffset, yoffset,
xoffset + width, yoffset + height
};
D3DLOCKED_RECT locked;
HRESULT result = lock(&locked, &lockRect);
......@@ -917,278 +927,17 @@ void Image::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsi
return;
}
GLsizei inputPitch = -ComputeCompressedPitch(width, mFormat);
GLsizei inputSize = ComputeCompressedSize(width, height, mFormat);
input = ((char*)input) + inputSize + inputPitch;
switch (getD3DFormat())
GLsizei inputPitch = ComputeCompressedPitch(width, mFormat);
int rows = inputSize / inputPitch;
for (int i = 0; i < rows; ++i)
{
case D3DFMT_DXT1:
loadDXT1Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
break;
case D3DFMT_DXT3:
loadDXT3Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
break;
case D3DFMT_DXT5:
loadDXT5Data(width, height, inputPitch, input, locked.Pitch, locked.pBits);
break;
memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch);
}
unlock();
}
static void FlipCopyDXT1BlockFull(const unsigned int* source, unsigned int* dest) {
// A DXT1 block layout is:
// [0-1] color0.
// [2-3] color1.
// [4-7] color bitmap, 2 bits per pixel.
// So each of the 4-7 bytes represents one line, flipping a block is just
// flipping those bytes.
// First 32-bits is two RGB565 colors shared by tile and does not need to be modified.
dest[0] = source[0];
// Second 32-bits contains 4 rows of 4 2-bit interpolants between the colors. All rows should be flipped.
dest[1] = (source[1] >> 24) |
((source[1] << 8) & 0x00FF0000) |
((source[1] >> 8) & 0x0000FF00) |
(source[1] << 24);
}
// Flips the first 2 lines of a DXT1 block in the y direction.
static void FlipCopyDXT1BlockHalf(const unsigned int* source, unsigned int* dest) {
// See layout above.
dest[0] = source[0];
dest[1] = ((source[1] << 8) & 0x0000FF00) |
((source[1] >> 8) & 0x000000FF);
}
// Flips a full DXT3 block in the y direction.
static void FlipCopyDXT3BlockFull(const unsigned int* source, unsigned int* dest) {
// A DXT3 block layout is:
// [0-7] alpha bitmap, 4 bits per pixel.
// [8-15] a DXT1 block.
// First and Second 32 bits are 4bit per pixel alpha and need to be flipped.
dest[0] = (source[1] >> 16) | (source[1] << 16);
dest[1] = (source[0] >> 16) | (source[0] << 16);
// And flip the DXT1 block using the above function.
FlipCopyDXT1BlockFull(source + 2, dest + 2);
}
// Flips the first 2 lines of a DXT3 block in the y direction.
static void FlipCopyDXT3BlockHalf(const unsigned int* source, unsigned int* dest) {
// See layout above.
dest[0] = (source[1] >> 16) | (source[1] << 16);
FlipCopyDXT1BlockHalf(source + 2, dest + 2);
}
// Flips a full DXT5 block in the y direction.
static void FlipCopyDXT5BlockFull(const unsigned int* source, unsigned int* dest) {
// A DXT5 block layout is:
// [0] alpha0.
// [1] alpha1.
// [2-7] alpha bitmap, 3 bits per pixel.
// [8-15] a DXT1 block.
// The alpha bitmap doesn't easily map lines to bytes, so we have to
// interpret it correctly. Extracted from
// http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt :
//
// The 6 "bits" bytes of the block are decoded into one 48-bit integer:
//
// bits = bits_0 + 256 * (bits_1 + 256 * (bits_2 + 256 * (bits_3 +
// 256 * (bits_4 + 256 * bits_5))))
//
// bits is a 48-bit unsigned integer, from which a three-bit control code
// is extracted for a texel at location (x,y) in the block using:
//
// code(x,y) = bits[3*(4*y+x)+1..3*(4*y+x)+0]
//
// where bit 47 is the most significant and bit 0 is the least
// significant bit.
const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
unsigned int line_2_3 = sourceBytes[5] + 256 * (sourceBytes[6] + 256 * sourceBytes[7]);
// swap lines 0 and 1 in line_0_1.
unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
((line_0_1 & 0xfff000) >> 12);
// swap lines 2 and 3 in line_2_3.
unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) |
((line_2_3 & 0xfff000) >> 12);
destBytes[0] = sourceBytes[0];
destBytes[1] = sourceBytes[1];
destBytes[2] = line_3_2 & 0xff;
destBytes[3] = (line_3_2 & 0xff00) >> 8;
destBytes[4] = (line_3_2 & 0xff0000) >> 16;
destBytes[5] = line_1_0 & 0xff;
destBytes[6] = (line_1_0 & 0xff00) >> 8;
destBytes[7] = (line_1_0 & 0xff0000) >> 16;
// And flip the DXT1 block using the above function.
FlipCopyDXT1BlockFull(source + 2, dest + 2);
}
// Flips the first 2 lines of a DXT5 block in the y direction.
static void FlipCopyDXT5BlockHalf(const unsigned int* source, unsigned int* dest) {
// See layout above.
const unsigned char* sourceBytes = static_cast<const unsigned char*>(static_cast<const void*>(source));
unsigned char* destBytes = static_cast<unsigned char*>(static_cast<void*>(dest));
unsigned int line_0_1 = sourceBytes[2] + 256 * (sourceBytes[3] + 256 * sourceBytes[4]);
unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) |
((line_0_1 & 0xfff000) >> 12);
destBytes[0] = sourceBytes[0];
destBytes[1] = sourceBytes[1];
destBytes[2] = line_1_0 & 0xff;
destBytes[3] = (line_1_0 & 0xff00) >> 8;
destBytes[4] = (line_1_0 & 0xff0000) >> 16;
FlipCopyDXT1BlockHalf(source + 2, dest + 2);
}
void Image::loadDXT1Data(GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const
{
ASSERT(width % 4 == 0 || width == 2 || width == 1);
ASSERT(inputPitch % 8 == 0);
ASSERT(outputPitch % 8 == 0);
const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
unsigned int *dest = reinterpret_cast<unsigned int*>(output);
// Round width up in case it is less than 4.
int blocksAcross = (width + 3) / 4;
int intsAcross = blocksAcross * 2;
switch (height)
{
case 1:
for (int x = 0; x < intsAcross; x += 2)
{
// just copy the block
dest[x] = source[x];
dest[x + 1] = source[x + 1];
}
break;
case 2:
for (int x = 0; x < intsAcross; x += 2)
{
FlipCopyDXT1BlockHalf(source + x, dest + x);
}
break;
default:
ASSERT(height % 4 == 0);
for (int y = 0; y < height / 4; ++y)
{
const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
for (int x = 0; x < intsAcross; x += 2)
{
FlipCopyDXT1BlockFull(source + x, dest + x);
}
}
break;
}
}
void Image::loadDXT3Data(GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const
{
ASSERT(width % 4 == 0 || width == 2 || width == 1);
ASSERT(inputPitch % 16 == 0);
ASSERT(outputPitch % 16 == 0);
const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
unsigned int *dest = reinterpret_cast<unsigned int*>(output);
// Round width up in case it is less than 4.
int blocksAcross = (width + 3) / 4;
int intsAcross = blocksAcross * 4;
switch (height)
{
case 1:
for (int x = 0; x < intsAcross; x += 4)
{
// just copy the block
dest[x] = source[x];
dest[x + 1] = source[x + 1];
dest[x + 2] = source[x + 2];
dest[x + 3] = source[x + 3];
}
break;
case 2:
for (int x = 0; x < intsAcross; x += 4)
{
FlipCopyDXT3BlockHalf(source + x, dest + x);
}
break;
default:
ASSERT(height % 4 == 0);
for (int y = 0; y < height / 4; ++y)
{
const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
for (int x = 0; x < intsAcross; x += 4)
{
FlipCopyDXT3BlockFull(source + x, dest + x);
}
}
break;
}
}
void Image::loadDXT5Data(GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const
{
ASSERT(width % 4 == 0 || width == 2 || width == 1);
ASSERT(inputPitch % 16 == 0);
ASSERT(outputPitch % 16 == 0);
const unsigned int *source = reinterpret_cast<const unsigned int*>(input);
unsigned int *dest = reinterpret_cast<unsigned int*>(output);
// Round width up in case it is less than 4.
int blocksAcross = (width + 3) / 4;
int intsAcross = blocksAcross * 4;
switch (height)
{
case 1:
for (int x = 0; x < intsAcross; x += 4)
{
// just copy the block
dest[x] = source[x];
dest[x + 1] = source[x + 1];
dest[x + 2] = source[x + 2];
dest[x + 3] = source[x + 3];
}
break;
case 2:
for (int x = 0; x < intsAcross; x += 4)
{
FlipCopyDXT5BlockHalf(source + x, dest + x);
}
break;
default:
ASSERT(height % 4 == 0);
for (int y = 0; y < height / 4; ++y)
{
const unsigned int *source = reinterpret_cast<const unsigned int*>(static_cast<const unsigned char*>(input) + y * inputPitch);
unsigned int *dest = reinterpret_cast<unsigned int*>(static_cast<unsigned char*>(output) + y * outputPitch);
for (int x = 0; x < intsAcross; x += 4)
{
FlipCopyDXT5BlockFull(source + x, dest + x);
}
}
break;
}
}
// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget)
{
......@@ -1214,9 +963,8 @@ void Image::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width,
return error(GL_OUT_OF_MEMORY);
}
RECT sourceRect = transformPixelRect(x, y, width, height, description.Height);
int destYOffset = transformPixelYOffset(yoffset, height, mHeight);
RECT destRect = {xoffset, destYOffset, xoffset + width, destYOffset + height};
RECT sourceRect = {x, y, x + width, y + height};
RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height};
if (isRenderableFormat())
{
......@@ -1971,19 +1719,17 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei
if (width != 0 && height != 0 && level < levelCount())
{
RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
GLint destYOffset = transformPixelYOffset(0, height, mImageArray[level].getHeight());
RECT sourceRect;
sourceRect.left = x;
sourceRect.right = x + width;
sourceRect.top = y;
sourceRect.bottom = y + height;
IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level);
if (dest)
{
getBlitter()->copy(renderTarget, sourceRect, format, 0, destYOffset, dest);
getBlitter()->copy(renderTarget, sourceRect, format, 0, 0, dest);
dest->Release();
}
}
......@@ -2023,19 +1769,18 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo
if (level < levelCount())
{
RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
RECT sourceRect;
sourceRect.left = x;
sourceRect.right = x + width;
sourceRect.top = y;
sourceRect.bottom = y + height;
GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[level].getHeight());
IDirect3DSurface9 *dest = mTexStorage->getSurfaceLevel(level);
if (dest)
{
getBlitter()->copy(renderTarget, sourceRect, mImageArray[0].getFormat(), xoffset, destYOffset, dest);
getBlitter()->copy(renderTarget, sourceRect, mImageArray[0].getFormat(), xoffset, yoffset, dest);
dest->Release();
}
}
......@@ -2923,19 +2668,17 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint
if (width > 0 && level < levelCount())
{
RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
GLint destYOffset = transformPixelYOffset(0, height, mImageArray[faceindex][level].getWidth());
RECT sourceRect;
sourceRect.left = x;
sourceRect.right = x + width;
sourceRect.top = y;
sourceRect.bottom = y + height;
IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level);
if (dest)
{
getBlitter()->copy(renderTarget, sourceRect, format, 0, destYOffset, dest);
getBlitter()->copy(renderTarget, sourceRect, format, 0, 0, dest);
dest->Release();
}
}
......@@ -2979,19 +2722,17 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi
if (level < levelCount())
{
RECT sourceRect = transformPixelRect(x, y, width, height, source->getColorbuffer()->getHeight());
sourceRect.left = clamp(sourceRect.left, 0, source->getColorbuffer()->getWidth());
sourceRect.top = clamp(sourceRect.top, 0, source->getColorbuffer()->getHeight());
sourceRect.right = clamp(sourceRect.right, 0, source->getColorbuffer()->getWidth());
sourceRect.bottom = clamp(sourceRect.bottom, 0, source->getColorbuffer()->getHeight());
GLint destYOffset = transformPixelYOffset(yoffset, height, mImageArray[faceindex][level].getWidth());
RECT sourceRect;
sourceRect.left = x;
sourceRect.right = x + width;
sourceRect.top = y;
sourceRect.bottom = y + height;
IDirect3DSurface9 *dest = mTexStorage->getCubeMapSurface(target, level);
if (dest)
{
getBlitter()->copy(renderTarget, sourceRect, mImageArray[0][0].getFormat(), xoffset, destYOffset, dest);
getBlitter()->copy(renderTarget, sourceRect, mImageArray[0][0].getFormat(), xoffset, yoffset, dest);
dest->Release();
}
}
......
......@@ -113,12 +113,6 @@ class Image
int inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
const void *input);
void loadDXT1Data(GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadDXT3Data(GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const;
void loadDXT5Data(GLsizei width, GLsizei height,
int inputPitch, const void *input, size_t outputPitch, void *output) const;
void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, IDirect3DSurface9 *renderTarget);
......
......@@ -70,26 +70,6 @@ inline unsigned int unorm(float x)
}
}
inline RECT transformPixelRect(GLint x, GLint y, GLint w, GLint h, GLint surfaceHeight)
{
RECT rect = {x,
surfaceHeight - y - h,
x + w,
surfaceHeight - y};
return rect;
}
inline int transformPixelYOffset(GLint yoffset, GLint h, GLint surfaceHeight)
{
return surfaceHeight - yoffset - h;
}
inline GLenum adjustWinding(GLenum winding)
{
ASSERT(winding == GL_CW || winding == GL_CCW);
return winding == GL_CW ? GL_CCW : GL_CW;
}
inline bool supportsSSE2()
{
static bool checked = false;
......
......@@ -612,9 +612,6 @@ D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
{
D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
// Map a cube map texture target to the corresponding D3D surface index. Note that the
// Y faces are swapped because the Y coordinate to the texture lookup intrinsic functions
// are negated in the pixel shader.
switch (cubeFace)
{
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
......@@ -624,10 +621,10 @@ D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace)
face = D3DCUBEMAP_FACE_NEGATIVE_X;
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
face = D3DCUBEMAP_FACE_NEGATIVE_Y;
face = D3DCUBEMAP_FACE_POSITIVE_Y;
break;
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
face = D3DCUBEMAP_FACE_POSITIVE_Y;
face = D3DCUBEMAP_FACE_NEGATIVE_Y;
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
face = D3DCUBEMAP_FACE_POSITIVE_Z;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment