diff options
author | Thorvald Natvig <slicer@users.sourceforge.net> | 2010-01-24 19:17:07 +0300 |
---|---|---|
committer | Thorvald Natvig <slicer@users.sourceforge.net> | 2010-01-24 19:17:35 +0300 |
commit | 0baf7589ad59a7ef8ecb6fff46bff4abf5c2afc9 (patch) | |
tree | 63a4b197d03a132dbed512095c18cedfa7551362 /overlay | |
parent | e54854686f98f9a5b0ba4f0150b97754893a9103 (diff) |
D3D9, D3D10 and OpenGL/Win32 pipe-based overlay
Diffstat (limited to 'overlay')
-rw-r--r-- | overlay/d3d10.cpp | 359 | ||||
-rw-r--r-- | overlay/d3d9.cpp | 229 | ||||
-rw-r--r-- | overlay/lib.cpp | 208 | ||||
-rw-r--r-- | overlay/lib.h | 22 | ||||
-rw-r--r-- | overlay/opengl.cpp | 220 | ||||
-rw-r--r-- | overlay/overlay.fx | 3 |
6 files changed, 599 insertions, 442 deletions
diff --git a/overlay/d3d10.cpp b/overlay/d3d10.cpp index 2ee65c209..96efbb9d0 100644 --- a/overlay/d3d10.cpp +++ b/overlay/d3d10.cpp @@ -61,7 +61,9 @@ struct SimpleVertex { D3DXVECTOR2 Tex; }; -struct D10State { +class D10State: protected Pipe { + public: + LONG lHighMark; LONG initRefCount; @@ -80,38 +82,169 @@ struct D10State { ID3D10Effect *pEffect; ID3D10EffectTechnique *pTechnique; ID3D10EffectShaderResourceVariable * pDiffuseTexture; - ID3D10EffectVectorVariable * pColor; ID3D10InputLayout *pVertexLayout; ID3D10Buffer *pVertexBuffer; ID3D10Buffer *pIndexBuffer; ID3D10BlendState *pBlendState; - ID3D10Texture2D *pTexture[NUM_TEXTS]; - ID3D10ShaderResourceView *pSRView[NUM_TEXTS]; - unsigned int uiCounter[NUM_TEXTS]; + ID3D10Texture2D *pTexture; + ID3D10ShaderResourceView *pSRView; + D10State(IDXGISwapChain *, ID3D10Device *); ~D10State(); void init(); void draw(); + + void blit(unsigned int x, unsigned int y, unsigned int w, unsigned int h); + void setRect(); + void newTexture(unsigned int w, unsigned int h); }; map<IDXGISwapChain *, D10State *> chains; map<ID3D10Device *, D10State *> devices; D10State::D10State(IDXGISwapChain *pSwapChain, ID3D10Device *pDevice) { - memset(this, 0, sizeof(*this)); - this->pSwapChain = pSwapChain; this->pDevice = pDevice; + lHighMark = initRefCount = refCount = myRefCount = 0; dwMyThread = 0; - refCount = 0; - myRefCount = 0; - + + ZeroMemory(&vp, sizeof(vp)); + + pOrigStateBlock = NULL; + pMyStateBlock = NULL; + pRTV = NULL; + pEffect = NULL; + pTechnique = NULL; + pDiffuseTexture = NULL; + pVertexLayout = NULL; + pVertexBuffer = NULL; + pIndexBuffer = NULL; + pBlendState = NULL; + pTexture = NULL; + pSRView = NULL; + pDevice->AddRef(); initRefCount = pDevice->Release(); } +void D10State::blit(unsigned int x, unsigned int y, unsigned int w, unsigned int h) { + HRESULT hr; + + ods("D3D10: Blit %d %d %d %d", x, y, w, h); + + if (! pTexture || ! pSRView) + return; + + D3D10_MAPPED_TEXTURE2D mappedTex; + hr = pTexture->Map(D3D10CalcSubresource(0, 0, 1), D3D10_MAP_WRITE_DISCARD, 0, &mappedTex); + if (FAILED(hr)) { + ods("D3D10: Failed map"); + } + + UCHAR* pTexels = (UCHAR*)mappedTex.pData; + + for (int r=0;r< uiHeight; ++r) { + unsigned char *sptr = a_ucTexture + r * uiWidth * 4; + unsigned char *dptr = reinterpret_cast<unsigned char *>(pTexels) + r * mappedTex.RowPitch; + memcpy(dptr, sptr, uiWidth * 4); + } + + pTexture->Unmap(D3D10CalcSubresource(0, 0, 1)); +} + +void D10State::setRect() { + HRESULT hr; + + ods("D3D10: Setrect"); + + float w = static_cast<float>(uiWidth); + float h = static_cast<float>(uiHeight); + + float left = static_cast<float>(uiLeft) - 0.5f; + float top = static_cast<float>(uiTop) - 0.5f; + float right = static_cast<float>(uiRight) + 0.5f; + float bottom = static_cast<float>(uiBottom) + 0.5f; + + float texl = (left) / w; + float text = (top) / h; + float texr = (right + 1.0f) / w; + float texb = (bottom + 1.0f) / h; + + left = 2.0f * (left / vp.Width) - 1.0f; + right = 2.0f * (right / vp.Width) - 1.0f; + top = -2.0f * (top / vp.Height) + 1.0f; + bottom = -2.0f * (bottom / vp.Height) + 1.0f; + + ods("Vertex (%f %f) (%f %f)", left, top, right, bottom); + + // Create vertex buffer + SimpleVertex vertices[] = { + { D3DXVECTOR3(left, top, 0.5f), D3DXVECTOR2(texl, text) }, + { D3DXVECTOR3(right, top, 0.5f), D3DXVECTOR2(texr, text) }, + { D3DXVECTOR3(right, bottom, 0.5f), D3DXVECTOR2(texr, texb) }, + { D3DXVECTOR3(left, bottom, 0.5f), D3DXVECTOR2(texl, texb) }, + }; + + void *pData = NULL; + + hr = pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &pData); + memcpy(pData, vertices, sizeof(vertices)); + ods("Map: %lx %d", hr, sizeof(vertices)); + pVertexBuffer->Unmap(); +} + +void D10State::newTexture(unsigned int w, unsigned int h) { + HRESULT hr; + + ods("D3D10: newTex %d %d", w, h); + + if (pTexture) { + pTexture->Release(); + pTexture = NULL; + } + if (pSRView) { + pSRView->Release(); + pSRView = NULL; + } + + D3D10_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + + desc.Width = w; + desc.Height = h; + desc.MipLevels = desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Usage = D3D10_USAGE_DYNAMIC; + desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; + desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; + hr = pDevice->CreateTexture2D(&desc, NULL, &pTexture); + + if (! SUCCEEDED(hr)) { + pTexture = NULL; + ods("D3D10: Failed to create texture."); + return; + } + + D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; + ZeroMemory(&srvDesc, sizeof(srvDesc)); + srvDesc.Format = desc.Format; + srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = desc.MipLevels; + + hr = pDevice->CreateShaderResourceView(pTexture, &srvDesc, &pSRView); + if (! SUCCEEDED(hr)) { + pSRView = NULL; + pTexture->Release(); + pTexture = NULL; + ods("D3D10: Failed to create resource view."); + return; + } +} + void D10State::init() { static HMODREF(GetModuleHandleW(L"D3D10.DLL"), D3D10CreateEffectFromMemory); static HMODREF(GetModuleHandleW(L"D3D10.DLL"), D3D10CreateStateBlock); @@ -169,13 +302,9 @@ void D10State::init() { pTechnique = pEffect->GetTechniqueByName("Render"); pDiffuseTexture = pEffect->GetVariableByName("txDiffuse")->AsShaderResource(); - pColor = pEffect->GetVariableByName("fColor")->AsVector(); - for (int i=0;i<NUM_TEXTS;++i) { - pTexture[i] = NULL; - pSRView[i] = NULL; - uiCounter[i] = 0; - } + pTexture = NULL; + pSRView = NULL; // Define the input layout D3D10_INPUT_ELEMENT_DESC layout[] = { @@ -235,12 +364,10 @@ D10State::~D10State() { pVertexLayout->Release(); pEffect->Release(); pRTV->Release(); - for (int i=0;i<NUM_TEXTS;++i) { - if (pTexture[i]) - pTexture[i]->Release(); - if (pSRView[i]) - pSRView[i]->Release(); - } + if (pTexture) + pTexture->Release(); + if (pSRView) + pSRView->Release(); pMyStateBlock->ReleaseAllDeviceObjects(); pMyStateBlock->Release(); @@ -250,198 +377,34 @@ D10State::~D10State() { } void D10State::draw() { - dwMyThread = GetCurrentThreadId(); - - pOrigStateBlock->Capture(); - pMyStateBlock->Apply(); - - int idx = 0; HRESULT hr; + dwMyThread = GetCurrentThreadId(); + + checkMessage(vp.Width, vp.Height); - vector<ID3D10ShaderResourceView *> texs; - vector<unsigned int> widths; - vector<unsigned int> yofs; - vector<DWORD> colors; - - unsigned int y = 0; - - if (sm->fFontSize < 0.01f) - sm->fFontSize = 0.01f; - else if (sm->fFontSize > 1.0f) - sm->fFontSize = 1.0f; - - int iHeight = lround(vp.Height * sm->fFontSize); - - if (iHeight > TEXT_HEIGHT) - iHeight = TEXT_HEIGHT; - - float s = iHeight / 60.0f; - - ods("D3D10: Init: Scale %f. iH %d. Final scale %f", sm->fFontSize, iHeight, s); - - DWORD dwWaitResult = WaitForSingleObject(hSharedMutex, 50L); - if (dwWaitResult == WAIT_OBJECT_0) { - for (int i=0;i<NUM_TEXTS;i++) { - if (sm->texts[i].width == 0) { - y += iHeight / 4; - } else if (sm->texts[i].width > 0) { - if (!pSRView[i] || (sm->texts[i].uiCounter != uiCounter[i])) { - if (pTexture[i]) - pTexture[i]->Release(); - if (pSRView[i]) - pSRView[i]->Release(); - - pTexture[i] = NULL; - pSRView[i] = NULL; - - D3D10_TEXTURE2D_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - - desc.Width = sm->texts[i].width; - desc.Height = TEXT_HEIGHT; - desc.MipLevels = desc.ArraySize = 1; - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - desc.SampleDesc.Count = 1; - desc.Usage = D3D10_USAGE_DYNAMIC; - desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE; - hr = pDevice->CreateTexture2D(&desc, NULL, &pTexture[i]); - ods("Setting %d by %d texture %d", desc.Width, desc.Height, i); - ods("%lx %p", hr, pTexture[i]); - - D3D10_MAPPED_TEXTURE2D mappedTex; - hr = pTexture[i]->Map(D3D10CalcSubresource(0, 0, 1), D3D10_MAP_WRITE_DISCARD, 0, &mappedTex); - - UCHAR* pTexels = (UCHAR*)mappedTex.pData; - - for (int r=0;r<TEXT_HEIGHT;r++) { - unsigned char *dptr = reinterpret_cast<unsigned char *>(pTexels) + r * mappedTex.RowPitch; - memcpy(dptr, sm->texts[i].texture + r * TEXT_WIDTH * 4, sm->texts[i].width * 4); - } - - pTexture[i]->Unmap(D3D10CalcSubresource(0, 0, 1)); - - D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = desc.Format; - srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MostDetailedMip = 0; - srvDesc.Texture2D.MipLevels = desc.MipLevels; - pDevice->CreateShaderResourceView(pTexture[i], &srvDesc, &pSRView[i]); - - uiCounter[i] = sm->texts[i].uiCounter; - } - unsigned int w = lround(sm->texts[i].width * s); - texs.push_back(pSRView[i]); - colors.push_back(sm->texts[i].color); - widths.push_back(w); - yofs.push_back(y); - idx++; - y += iHeight; - } - } - ReleaseMutex(hSharedMutex); - } - - if (idx == 0) - return; - - int height = y; - y = lround(vp.Height * sm->fY); - - if (sm->bTop) { - y -= height; - } else if (sm->bBottom) { - } else { - y -= height / 2; - } - - - if (y < 1) - y = 1; - if ((y + height + 1) > vp.Height) - y = vp.Height - height - 1; - - D3D10_TECHNIQUE_DESC techDesc; - pTechnique->GetDesc(&techDesc); - - for (int i=0;i<idx;i++) { - unsigned int width = widths[i]; - - int x = lround(vp.Width * sm->fX); - - if (sm->bLeft) { - x -= width; - } else if (sm->bRight) { - } else { - x -= width / 2; - } - - if (x < 1) - x = 1; - if ((x + width + 1) > vp.Width) - x = vp.Width - width - 1; - -// D3DCOLOR color = colors[i]; - - float cols[] = { - ((colors[i] >> 24) & 0xFF) / 255.0f, - ((colors[i] >> 16) & 0xFF) / 255.0f, - ((colors[i] >> 8) & 0xFF) / 255.0f, - ((colors[i] >> 0) & 0xFF) / 255.0f, - }; - - float left = static_cast<float>(x); - float top = static_cast<float>(y + yofs[i]); - float right = left + width; - float bottom = top + iHeight; - - left = 2.0f * (left / vp.Width) - 1.0f; - right = 2.0f * (right / vp.Width) - 1.0f; - top = -2.0f * (top / vp.Height) + 1.0f; - bottom = -2.0f * (bottom / vp.Height) + 1.0f; - - ods("Vertex (%f %f) (%f %f)", left, top, right, bottom); - - // Create vertex buffer - SimpleVertex vertices[] = { - { D3DXVECTOR3(left, top, 0.5f), D3DXVECTOR2(0.0f, 0.0f) }, - { D3DXVECTOR3(right, top, 0.5f), D3DXVECTOR2(1.0f, 0.0f) }, - { D3DXVECTOR3(right, bottom, 0.5f), D3DXVECTOR2(1.0f, 1.0f) }, - { D3DXVECTOR3(left, bottom, 0.5f), D3DXVECTOR2(0.0f, 1.0f) }, - }; - - void *pData = NULL; + if (a_ucTexture && pSRView && (uiLeft != uiRight)) { + pOrigStateBlock->Capture(); + pMyStateBlock->Apply(); - hr = pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &pData); - memcpy(pData, vertices, sizeof(vertices)); - ods("Map: %lx %d", hr, sizeof(vertices)); - pVertexBuffer->Unmap(); + D3D10_TECHNIQUE_DESC techDesc; + pTechnique->GetDesc(&techDesc); // Set vertex buffer UINT stride = sizeof(SimpleVertex); UINT offset = 0; pDevice->IASetVertexBuffers(0, 1, &pVertexBuffer, &stride, &offset); - hr = pDiffuseTexture->SetResource(texs[i]); - ods("setres %p %lx", pDiffuseTexture, hr); - - hr = pColor->SetFloatVector(cols); - ods("setres %p %lx", pColor, hr); - - ods("%f %f %f %f", cols[0], cols[1], cols[2], cols[3]); + hr = pDiffuseTexture->SetResource(pSRView); + if (! SUCCEEDED(hr)) + ods("D3D10: Failed to set resource"); for (UINT p = 0; p < techDesc.Passes; ++p) { - // ods("Pass %d", p); pTechnique->GetPassByIndex(p)->Apply(0); pDevice->DrawIndexed(6, 0, 0); } + pOrigStateBlock->Apply(); } - - // Render a triangle - pOrigStateBlock->Apply(); - dwMyThread = 0; } diff --git a/overlay/d3d9.cpp b/overlay/d3d9.cpp index 2635bd201..2910f9433 100644 --- a/overlay/d3d9.cpp +++ b/overlay/d3d9.cpp @@ -38,12 +38,11 @@ typedef HRESULT(WINAPI *pDirect3DCreate9Ex)(UINT SDKVersion, IDirect3D9Ex **ppD3 struct D3DTLVERTEX { float x, y, z, rhw; // Position - D3DCOLOR color; // Vertex colour float tu, tv; // Texture coordinates }; -const DWORD D3DFVF_TLVERTEX = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1; +const DWORD D3DFVF_TLVERTEX = D3DFVF_XYZRHW | D3DFVF_TEX1; -class DevState { +class DevState : protected Pipe { public: IDirect3DDevice9 *dev; IDirect3DStateBlock9 *pSB; @@ -52,9 +51,9 @@ class DevState { LONG refCount; LONG myRefCount; DWORD dwMyThread; - - LPDIRECT3DTEXTURE9 tex[NUM_TEXTS]; - unsigned int uiCounter[NUM_TEXTS]; + + D3DTLVERTEX vertices[4]; + LPDIRECT3DTEXTURE9 texTexture; DevState(); @@ -63,6 +62,10 @@ class DevState { void releaseAll(); void draw(); void postDraw(); + + void blit(unsigned int x, unsigned int y, unsigned int w, unsigned int h); + void setRect(); + void newTexture(unsigned int width, unsigned int height); }; static map<IDirect3DDevice9 *, DevState *> devMap; @@ -76,145 +79,123 @@ DevState::DevState() { dwMyThread = 0; refCount = 0; myRefCount = 0; - for (int i = 0;i < NUM_TEXTS;i++) - tex[i] = NULL; + texTexture = NULL; + + for(int i=0;i<4;++i) { + vertices[i].x = vertices[i].y = 0.0f; + vertices[i].tu = vertices[i].tv = 0.0f; + vertices[i].z = vertices[i].rhw = 1.0f; + } } void DevState::releaseData() { ods("D3D9: Release Data"); - for (int i=0;i<NUM_TEXTS;i++) - if (tex[i]) { - tex[i]->Release(); - tex[i] = NULL; - } -} - -void DevState::releaseAll() { - ods("D3D9: Release All"); - releaseData(); - if (pSB) - pSB->Release(); - pSB = NULL; + if (texTexture) { + texTexture->Release(); + texTexture = NULL; + } } -void DevState::draw() { - D3DVIEWPORT9 vp; - dev->GetViewport(&vp); - - int idx = 0; - - vector<LPDIRECT3DTEXTURE9> texs; - vector<unsigned int> widths; - vector<unsigned int> yofs; - vector<DWORD> colors; - - unsigned int y = 0; - - if (sm->fFontSize < 0.01f) - sm->fFontSize = 0.01f; - else if (sm->fFontSize > 1.0f) - sm->fFontSize = 1.0f; - - int iHeight = lround(vp.Height * sm->fFontSize); - - if (iHeight > TEXT_HEIGHT) - iHeight = TEXT_HEIGHT; - - float s = iHeight / 60.0f; - - ods("D3D9: Init: Scale %f. iH %d. Final scale %f", sm->fFontSize, iHeight, s); - - DWORD dwWaitResult = WaitForSingleObject(hSharedMutex, 50L); - if (dwWaitResult == WAIT_OBJECT_0) { - for (int i=0;i<NUM_TEXTS;i++) { - if (sm->texts[i].width == 0) { - y += iHeight / 4; - } else if (sm->texts[i].width > 0) { - if (!tex[i] || (sm->texts[i].uiCounter != uiCounter[i])) { - if (tex[i]) - tex[i]->Release(); - - dev->CreateTexture(sm->texts[i].width, TEXT_HEIGHT, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex[i], NULL); +void DevState::blit(unsigned int x, unsigned int y, unsigned int w, unsigned int h) { + ods("D3D9: Blit %d %d %d %d", x, y, w, h); + + if (! texTexture) + return; - D3DLOCKED_RECT lr; - tex[i]->LockRect(0, &lr, NULL, D3DLOCK_DISCARD); + D3DLOCKED_RECT lr; + RECT r; + + r.left = x; + r.top = y; + r.right = x + w; + r.bottom = y + h; - for (int r=0;r<TEXT_HEIGHT;r++) { - unsigned char *dptr = reinterpret_cast<unsigned char *>(lr.pBits) + r * lr.Pitch; - memcpy(dptr, sm->texts[i].texture + r * TEXT_WIDTH * 4, sm->texts[i].width * 4); - } + if (texTexture->LockRect(0, &lr, &r, 0) != D3D_OK) + return; - tex[i]->UnlockRect(0); - uiCounter[i] = sm->texts[i].uiCounter; - } - unsigned int w = lround(sm->texts[i].width * s); - texs.push_back(tex[i]); - colors.push_back(sm->texts[i].color); - widths.push_back(w); - yofs.push_back(y); - idx++; - y += iHeight; - } - } - ReleaseMutex(hSharedMutex); + for (unsigned int r=0;r < h;++r) { + unsigned char *dptr = reinterpret_cast<unsigned char *>(lr.pBits) + r * lr.Pitch; + unsigned char *sptr = a_ucTexture + 4 * ((y + r) * uiWidth + x); + memcpy(dptr, sptr, w * 4); } - if (idx == 0) - return; + texTexture->UnlockRect(0); +} - int height = y; - y = lround(vp.Height * sm->fY); +void DevState::setRect() { + ods("D3D9: New subrect"); + + float w = static_cast<float>(uiWidth); + float h = static_cast<float>(uiHeight); + + float left = static_cast<float>(uiLeft) - 0.5f; + float top = static_cast<float>(uiTop) - 0.5f; + float right = static_cast<float>(uiRight) + 0.5f; + float bottom = static_cast<float>(uiBottom) + 0.5f; + + float texl = (left) / w; + float text = (top) / h; + float texr = (right + 1.0f) / w; + float texb = (bottom + 1.0f) / h; + + vertices[0].x = left; + vertices[0].y = top; + vertices[0].tu = texl; + vertices[0].tv = text; + + vertices[1].x = right; + vertices[1].y = top; + vertices[1].tu = texr; + vertices[1].tv = text; + + vertices[2].x = right; + vertices[2].y = bottom; + vertices[2].tu = texr; + vertices[2].tv = texb; + + vertices[3].x = left; + vertices[3].y = bottom; + vertices[3].tu = texl; + vertices[3].tv = texb; +} - if (sm->bTop) { - y -= height; - } else if (sm->bBottom) { - } else { - y -= height / 2; +void DevState::newTexture(unsigned int width, unsigned int height) { + ods("D3D9: New texture %d x %d", width, height); + + if (texTexture) { + texTexture->Release(); + texTexture = NULL; } + dev->CreateTexture(uiWidth, uiHeight, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texTexture, NULL); - if (y < 1) - y = 1; - if ((y + height + 1) > vp.Height) - y = vp.Height - height - 1; + for(int i=0;i<4;++i) { + vertices[i].x = vertices[i].y = vertices[i].z = 0.0f; + vertices[i].tu = vertices[i].tv = 0.0f; + vertices[i].rhw = 1.0f; + } +} - for (int i=0;i<idx;i++) { - unsigned int width = widths[i]; +void DevState::releaseAll() { + ods("D3D9: Release All"); + releaseData(); + if (pSB) + pSB->Release(); + pSB = NULL; +} - int x = lround(vp.Width * sm->fX); +void DevState::draw() { + D3DVIEWPORT9 vp; + dev->GetViewport(&vp); - if (sm->bLeft) { - x -= width; - } else if (sm->bRight) { - } else { - x -= width / 2; - } + checkMessage(vp.Width, vp.Height); + + if (! a_ucTexture || !texTexture || (uiLeft == uiRight)) + return; - if (x < 1) - x = 1; - if ((x + width + 1) > vp.Width) - x = vp.Width - width - 1; - - D3DCOLOR color = colors[i]; - - float left = static_cast<float>(x); - float top = static_cast<float>(y + yofs[i]); - float right = left + width; - float bottom = top + iHeight; - - const float z = 1.0f; - D3DTLVERTEX vertices[4] = { - // x, y, z, color, tu, tv - { left, top, z, 1, color, 0, 0 }, - { right, top, z, 1, color, 1, 0 }, - { right, bottom, z, 1, color, 1, 1 }, - { left, bottom, z, 1, color, 0, 1 } - }; - - dev->SetTexture(0, texs[i]); - dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertices, sizeof(D3DTLVERTEX)); - } + dev->SetTexture(0, texTexture); + dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertices, sizeof(D3DTLVERTEX)); } void DevState::createCleanState() { diff --git a/overlay/lib.cpp b/overlay/lib.cpp index 4d563a60b..632f118d5 100644 --- a/overlay/lib.cpp +++ b/overlay/lib.cpp @@ -397,6 +397,205 @@ void __cdecl ods(const char *format, ...) { OutputDebugStringA(buf); } +Pipe::Pipe() { + hSocket = INVALID_HANDLE_VALUE; + hMemory = NULL; + a_ucTexture = NULL; + + omMsg.omh.iLength = -1; + + uiWidth = uiHeight = 0; + uiLeft = uiRight = uiTop = uiBottom = 0; +} + +Pipe::~Pipe() { + disconnect(); +} + +void Pipe::release() { + if (hMemory) { + CloseHandle(hMemory); + hMemory = NULL; + if (a_ucTexture) { + UnmapViewOfFile(a_ucTexture); + a_ucTexture = NULL; + } + + uiLeft = uiRight = uiTop = uiBottom = 0; + } +} + +void Pipe::disconnect() { + release(); + if (hSocket != INVALID_HANDLE_VALUE) { + ods("Pipe: Disconnect"); + CloseHandle(hSocket); + hSocket = INVALID_HANDLE_VALUE; + } + uiWidth = 0; + uiHeight = 0; + omMsg.omh.iLength = -1; +} + +bool Pipe::sendMessage(const OverlayMsg &om) { + DWORD dwBytesToWrite = sizeof(OverlayMsgHeader) + om.omh.iLength; + DWORD dwBytesWritten = dwBytesToWrite; + + if (WriteFile(hSocket, om.headerbuffer, sizeof(OverlayMsgHeader) + om.omh.iLength, &dwBytesWritten, NULL)) + if (dwBytesToWrite == dwBytesWritten) + return true; + + ods("Pipe: Short write"); + disconnect(); + return false; +} + +void Pipe::checkMessage(unsigned int w, unsigned int h) { + if (!w || ! h) + return; + + if (hSocket == INVALID_HANDLE_VALUE) { + hSocket = CreateFileW(L"\\\\.\\pipe\\MumbleOverlayPipe", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (hSocket == INVALID_HANDLE_VALUE) { + ods("Pipe: Connection failed"); + return; + } + ods("Pipe: Connected"); + + uiWidth = 0; + uiHeight = 0; + } + + if ((uiWidth != w) || (uiHeight != h)) { + release(); + + uiWidth = w; + uiHeight = h; + + OverlayMsg om; + om.omh.uiMagic = OVERLAY_MAGIC_NUMBER; + om.omh.uiType = OVERLAY_MSGTYPE_INIT; + om.omh.iLength = sizeof(OverlayMsgInit); + om.omi.uiWidth = uiWidth; + om.omi.uiHeight = uiHeight; + + if (!sendMessage(om)) + return; + + ods("Pipe: SentInit %d %d", w, h); + } + + while(1) { + DWORD dwBytesLeft; + DWORD dwBytesRead; + + if (! PeekNamedPipe(hSocket, NULL, 0, NULL, &dwBytesLeft, NULL)) { + ods("Pipe: No peek"); + disconnect(); + return; + } + + if (omMsg.omh.iLength == -1) { + if (dwBytesLeft < sizeof(OverlayMsgHeader)) + break; + + ReadFile(hSocket, omMsg.headerbuffer, sizeof(OverlayMsgHeader), &dwBytesRead, NULL); + dwBytesLeft -= sizeof(OverlayMsgHeader); + + if (dwBytesRead != sizeof(OverlayMsgHeader)) { + ods("Pipe: Short header read %d", dwBytesRead); + disconnect(); + return; + } + } + + if (static_cast<int>(dwBytesLeft) < omMsg.omh.iLength) + break; + + ReadFile(hSocket, omMsg.msgbuffer, omMsg.omh.iLength, &dwBytesRead, NULL); + if (dwBytesRead != omMsg.omh.iLength) { + ods("Pipe: Short body read %d/%d", dwBytesRead, omMsg.omh.iLength); + disconnect(); + return; + } + + switch(omMsg.omh.uiType) { + case OVERLAY_MSGTYPE_SHMEM: { + wchar_t memname[2048]; + memname[0] = 0; + + MultiByteToWideChar(CP_UTF8, 0, omMsg.oms.a_cName, omMsg.omh.iLength, memname, 2048); + + release(); + + hMemory = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, uiWidth * uiHeight * 4, memname); + + if (GetLastError() != ERROR_ALREADY_EXISTS) { + ods("Pipe: Memory %s(%d) => %ls doesn't exist", omMsg.oms.a_cName, omMsg.omh.iLength, memname); + if (hMemory) { + CloseHandle(hMemory); + hMemory = NULL; + break; + } + } + + if (! hMemory) { + ods("Pipe: CreateFileMapping failed"); + break; + } + + a_ucTexture = reinterpret_cast<unsigned char *>(MapViewOfFile(hMemory, FILE_MAP_ALL_ACCESS, 0, 0, 0)); + + if (a_ucTexture == NULL) { + ods("Pipe: Failed to map memory"); + CloseHandle(hMemory); + hMemory = NULL; + } + + MEMORY_BASIC_INFORMATION mbi; + memset(&mbi, 0, sizeof(mbi)); + if ((VirtualQuery(a_ucTexture, &mbi, sizeof(mbi)) == 0) || (mbi.RegionSize < (uiHeight * uiWidth * 4))) { + ods("Pipe: Memory too small"); + UnmapViewOfFile(a_ucTexture); + CloseHandle(hMemory); + a_ucTexture = NULL; + hMemory = NULL; + break; + } + + OverlayMsg om; + om.omh.uiMagic = OVERLAY_MAGIC_NUMBER; + om.omh.uiType = OVERLAY_MSGTYPE_SHMEM; + om.omh.iLength = 0; + + if (!sendMessage(om)) + return; + + newTexture(uiWidth, uiHeight); + } + break; + case OVERLAY_MSGTYPE_BLIT: { + if (a_ucTexture) + blit(omMsg.omb.x, omMsg.omb.y, omMsg.omb.w, omMsg.omb.h); + } + break; + case OVERLAY_MSGTYPE_ACTIVE: { + uiLeft = omMsg.oma.x; + uiTop = omMsg.oma.y; + uiRight = omMsg.oma.x + omMsg.oma.w; + uiBottom = omMsg.oma.y + omMsg.oma.h; + if (a_ucTexture) + setRect(); + } + break; + default: + break; + } + omMsg.omh.iLength = -1; + } +} + +static bool bBlackListed = false; static const char *blacklist[] = { "iexplore.exe", "ieuser.exe", @@ -413,7 +612,7 @@ static HMODULE WINAPI MyLoadLibrary(const char *lpFileName) { hhLoad.restore(); HMODULE h = oLoadLibrary(lpFileName); - ods("Library %s loaded to %p", lpFileName, h); +// ods("Library %s loaded to %p", lpFileName, h); if (! bMumble) { checkD3D9Hook(); @@ -498,7 +697,6 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID) { switch (fdwReason) { case DLL_PROCESS_ATTACH: { Mutex::init(); - ods("Lib: ProcAttach: %s", procname); char *p = strrchr(procname, '\\'); if (p) { @@ -507,7 +705,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID) { int i =0; while (blacklist[i]) { if (_stricmp(p+1,blacklist[i])==0) { - ods("Process %s is blacklisted", procname); + bBlackListed = true; return TRUE; } i++; @@ -531,6 +729,8 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID) { } } + ods("Lib: ProcAttach: %s", procname); + hSharedMutex = CreateMutex(NULL, false, "MumbleSharedMutex"); hHookMutex = CreateMutex(NULL, false, "MumbleHookMutex"); if ((hSharedMutex == NULL) || (hHookMutex == NULL)) { @@ -596,6 +796,8 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD fdwReason, LPVOID) { } break; case DLL_PROCESS_DETACH: { + if (bBlackListed) + return TRUE; ods("Lib: ProcDetach: %s", procname); hhLoad.restore(true); hhLoadW.restore(true); diff --git a/overlay/lib.h b/overlay/lib.h index 3d1621f61..243f32213 100644 --- a/overlay/lib.h +++ b/overlay/lib.h @@ -107,6 +107,28 @@ class Mutex { ~Mutex(); }; +class Pipe { + private: + HANDLE hSocket; + HANDLE hMemory; + + void release(); + void disconnect(); + protected: + unsigned int uiWidth, uiHeight; + unsigned int uiLeft, uiTop, uiRight, uiBottom; + unsigned char *a_ucTexture; + OverlayMsg omMsg; + + void checkMessage(unsigned int w, unsigned int h); + bool sendMessage(const OverlayMsg &m); + virtual void blit(unsigned int x, unsigned int y, unsigned int w, unsigned int h) = 0; + virtual void setRect() = 0; + virtual void newTexture(unsigned int w, unsigned int h) = 0; + Pipe(); + ~Pipe(); +}; + extern void checkDXGIHook(bool preonly = false); extern void checkD3D9Hook(bool preonly = false); extern void checkOpenGLHook(); diff --git a/overlay/opengl.cpp b/overlay/opengl.cpp index 16a9d090a..33e3011f3 100644 --- a/overlay/opengl.cpp +++ b/overlay/opengl.cpp @@ -50,6 +50,7 @@ typedef double GLdouble; #define GL_CLAMP_TO_EDGE 0x812F #define GL_TEXTURE_MAG_FILTER 0x2800 #define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_NEAREST 0x2600 #define GL_LINEAR 0x2601 #define GL_FRONT_AND_BACK 0x0408 #define GL_AMBIENT_AND_DIFFUSE 0x1602 @@ -81,12 +82,16 @@ typedef double GLdouble; #define GL_MODELVIEW 0x1700 #define GL_PROJECTION 0x1701 #define GL_BLEND 0x0BE2 +#define GL_TEXTURE_ENV 0x2300 +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_REPLACE 0x1E01 #define TDEF(ret, name, arg) typedef ret (__stdcall * t##name) arg #define GLDEF(ret, name, arg) TDEF(ret, name, arg); t##name o##name = NULL GLDEF(HGLRC, wglCreateContext, (HDC)); GLDEF(void, glGenTextures, (GLsizei, GLuint *)); +GLDEF(void, glDeleteTextures, (GLsizei, GLuint *)); GLDEF(void, glEnable, (GLenum)); GLDEF(void, glDisable, (GLenum)); GLDEF(void, glBlendFunc, (GLenum, GLenum)); @@ -105,7 +110,9 @@ GLDEF(void, glTexCoord2f, (GLfloat, GLfloat)); GLDEF(void, glVertex2f, (GLfloat, GLfloat)); GLDEF(void, glPopMatrix, (void)); GLDEF(void, glTexParameteri, (GLenum, GLenum, GLint)); +GLDEF(void, glTexEnvi, (GLenum, GLenum, GLint)); GLDEF(void, glTexImage2D, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *)); +GLDEF(void, glTexSubImage2D, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *)); GLDEF(void, wglMakeCurrent, (HDC, HGLRC)); GLDEF(HGLRC, wglGetCurrentContext, (void)); GLDEF(HDC, wglGetCurrentDC, (void)); @@ -121,12 +128,19 @@ INJDEF(BOOL, SwapBuffers, (HDC)); static bool bHooked = false; static bool bChaining = false; -struct Context { - HGLRC ctx; - GLuint textures[NUM_TEXTS]; - unsigned int uiCounter[NUM_TEXTS]; - Context(HDC hdc); - void draw(HDC hdc); +class Context : protected Pipe { + public: + HGLRC ctx; + GLuint textures[NUM_TEXTS]; + GLuint texture; + unsigned int uiCounter[NUM_TEXTS]; + + Context(HDC hdc); + void draw(HDC hdc); + + void blit(unsigned int x, unsigned int y, unsigned int w, unsigned int h); + void setRect(); + void newTexture(unsigned int width, unsigned int height); }; Context::Context(HDC hdc) { @@ -141,7 +155,7 @@ Context::Context(HDC hdc) { oglEnable(GL_BLEND); // Skip clip planes, there are thousands of them. oglDisable(GL_COLOR_LOGIC_OP); - oglEnable(GL_COLOR_MATERIAL); + oglDisable(GL_COLOR_MATERIAL); oglDisable(GL_COLOR_TABLE); oglDisable(GL_CONVOLUTION_1D); oglDisable(GL_CONVOLUTION_2D); @@ -166,16 +180,59 @@ Context::Context(HDC hdc) { oglDisable(GL_TEXTURE_GEN_T); oglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - oglColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + + texture = ~0; +} - DWORD dwWaitResult = WaitForSingleObject(hSharedMutex, 50L); - if (dwWaitResult != WAIT_OBJECT_0) +void Context::blit(unsigned int x, unsigned int y, unsigned int w, unsigned int h) { + ods("OpenGL: Blit %d %d %d %d -- %d %d : %d", x, y, w, h, uiWidth, uiHeight, texture); + + if (texture == ~0) return; - for (int i=0;i<NUM_TEXTS;++i) - uiCounter[i] = 0; + oglBindTexture(GL_TEXTURE_2D, texture); + + if ((x == 0) && (y == 0) && (w == uiWidth) && (h == uiHeight)) { + oglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, uiWidth, uiHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, a_ucTexture); + } else { + unsigned char *ptr = new unsigned char[w*h*4]; + memset(ptr, 0xff, w * h * 4); + + for(int r = 0; r < h; ++r) { + const unsigned char *sptr = a_ucTexture + 4 * ((y+r) * uiWidth + x); + unsigned char *dptr = ptr + 4 * w * r; + memcpy(dptr, sptr, w * 4); + } + + oglTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_BGRA, GL_UNSIGNED_BYTE, ptr); + delete [] ptr; + } +} + +void Context::setRect() { + ods("OpenGL: setRect"); +} + +void Context::newTexture(unsigned int width, unsigned int height) { + ods("OpenGL: newTex"); - ReleaseMutex(hSharedMutex); + if (texture == ~0) { + oglBindTexture(GL_TEXTURE_2D, 0); + oglDeleteTextures(1, &texture); + texture = ~0; + } + oglGenTextures(1, &texture); + + oglBindTexture(GL_TEXTURE_2D, texture); + oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + unsigned char *ptr = new unsigned char[width*height*4]; + memset(ptr, 0, width*height*4); + oglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, ptr); + delete [] ptr; } void Context::draw(HDC hdc) { @@ -185,35 +242,13 @@ void Context::draw(HDC hdc) { // sm->bDebug = true; unsigned int width, height; - int i; width = oGetDeviceCaps(hdc, HORZRES); height = oGetDeviceCaps(hdc, VERTRES); - ods("DrawStart: Screen is %d x %d", width, height); - - if (sm->fFontSize < 0.01f) - sm->fFontSize = 0.01f; - else if (sm->fFontSize > 1.0f) - sm->fFontSize = 1.0f; - - int iHeight = (int)((height * 1.0) * sm->fFontSize); - if (iHeight > TEXT_HEIGHT) - iHeight = TEXT_HEIGHT; - - float s = iHeight / 60.0f; - int y = 0; - int idx = 0; - - int texs[NUM_TEXTS]; - int widths[NUM_TEXTS]; - int yofs[NUM_TEXTS]; - unsigned int color[NUM_TEXTS]; - - - DWORD dwWaitResult = WaitForSingleObject(hSharedMutex, 50L); - if (dwWaitResult != WAIT_OBJECT_0) - return; + ods("OpenGL: DrawStart: Screen is %d x %d", width, height); + + checkMessage(width, height); oglViewport(0, 0, width, height); @@ -223,89 +258,41 @@ void Context::draw(HDC hdc) { oglMatrixMode(GL_MODELVIEW); - for (i = 0; i < NUM_TEXTS; i++) { - if (sm->texts[i].width == 0) { - y += iHeight / 4; - } else if (sm->texts[i].width > 0) { - if (sm->texts[i].uiCounter != uiCounter[i]) { - ods("OpenGL: Updating %d %d texture", sm->texts[i].width, TEXT_HEIGHT); - oglBindTexture(GL_TEXTURE_2D, textures[i]); - oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - oglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - oglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXT_WIDTH, TEXT_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_BYTE, sm->texts[i].texture); - uiCounter[i] = sm->texts[i].uiCounter; - } - texs[idx] = textures[i]; - widths[idx] = sm->texts[i].width; - color[idx] = sm->texts[i].color; - yofs[idx] = y; - y += iHeight; - idx++; - } - } - ReleaseMutex(hSharedMutex); + oglBindTexture(GL_TEXTURE_2D, texture); + oglPushMatrix(); + oglLoadIdentity(); - int h = y; - y = (int)(height * sm->fY); + float w = static_cast<float>(uiWidth); + float h = static_cast<float>(uiHeight); - if (sm->bTop) { - y -= h; - } else if (sm->bBottom) { - } else { - y -= h / 2; - } + float left = static_cast<float>(uiLeft); + float top = static_cast<float>(uiTop); + float right = static_cast<float>(uiRight); + float bottom = static_cast<float>(uiBottom); - if (y < 1) - y = 1; - if ((y + h + 1) > (int)height) - y = height - h - 1; + float xm = (left) / w; + float ym = (top) / h; + float xmx = (right) / w; + float ymx = (bottom) / h; + oglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + oglBegin(GL_QUADS); - for (i = 0; i < idx; i++) { - int w = (int)(widths[i] * s); - int x = (int)(width * sm->fX); - if (sm->bLeft) { - x -= w; - } else if (sm->bRight) { - } else { - x -= w / 2; - } + oglTexCoord2f(xm, ymx); + oglVertex2f(left, bottom); + + oglTexCoord2f(xm, ym); + oglVertex2f(left, top); + + oglTexCoord2f(xmx, ym); + oglVertex2f(right, top); + + oglTexCoord2f(xmx, ymx); + oglVertex2f(right, bottom); + oglEnd(); + + oglPopMatrix(); - if (x < 1) - x = 1; - if ((x + w + 1) > (int)width) - x = width - w - 1; - - ods("OpenGL: Drawing text at %d %d %d %d", x, y + yofs[i], w, iHeight); - oglBindTexture(GL_TEXTURE_2D, texs[i]); - oglPushMatrix(); - oglLoadIdentity(); - - float xm = 0.0; - float ym = 0.0; - float xmx = (1.0f * widths[i]) / TEXT_WIDTH; - float ymx = 1.0f; - - unsigned int c = color[i]; - - oglColor4ub((c >> 16) & 0xFF, (c >> 8) & 0xFF, c & 0xFF, (c >> 24) & 0xFF); - - - oglTranslatef(static_cast<float>(x), static_cast<float>(y + yofs[i]), 0.0f); - oglBegin(GL_QUADS); - oglTexCoord2f(xm, ymx); - oglVertex2f(0.0f, static_cast<float>(iHeight)); - oglTexCoord2f(xm, ym); - oglVertex2f(0.0f, 0.0f); - oglTexCoord2f(xmx, ym); - oglVertex2f(static_cast<float>(w), 0.0f); - oglTexCoord2f(xmx, ymx); - oglVertex2f(static_cast<float>(w), static_cast<float>(iHeight)); - oglEnd(); - oglPopMatrix(); - } } static map<HDC, Context *> contexts; @@ -381,6 +368,7 @@ void checkOpenGLHook() { GLDEF(wglCreateContext); GLDEF(glGenTextures); + GLDEF(glDeleteTextures); GLDEF(glEnable); GLDEF(glDisable); GLDEF(glBlendFunc); @@ -399,7 +387,9 @@ void checkOpenGLHook() { GLDEF(glVertex2f); GLDEF(glPopMatrix); GLDEF(glTexParameteri); + GLDEF(glTexEnvi); GLDEF(glTexImage2D); + GLDEF(glTexSubImage2D); GLDEF(wglMakeCurrent); GLDEF(wglGetCurrentContext); GLDEF(wglGetCurrentDC); diff --git a/overlay/overlay.fx b/overlay/overlay.fx index 9d2774e30..b06454f52 100644 --- a/overlay/overlay.fx +++ b/overlay/overlay.fx @@ -1,5 +1,4 @@ Texture2D txDiffuse; -float4 fColor; SamplerState samLinear { Filter = MIN_MAG_MIP_LINEAR; @@ -29,7 +28,7 @@ PS_INPUT VS( VS_INPUT input ) float4 PS( PS_INPUT input ) : SV_Target { - return txDiffuse.Sample(samLinear, input.Tex).bgra * fColor; + return txDiffuse.Sample(samLinear, input.Tex).bgra; } technique10 Render |