void mpRendererD3D9::updateDataTexture(void *texptr, int width, int height, const void *data, size_t data_size) { int psize = 16; HRESULT hr; IDirect3DTexture9 *tex = (IDirect3DTexture9*)texptr; // D3D11 と違い、D3D9 では書き込みも staging texture を経由する必要がある。 IDirect3DSurface9 *surf_src = findOrCreateStagingTexture(mpDataTextureWidth, height); if (surf_src == nullptr) { return; } IDirect3DSurface9* surf_dst = nullptr; hr = tex->GetSurfaceLevel(0, &surf_dst); if (FAILED(hr)) { return; } bool ret = false; D3DLOCKED_RECT locked; hr = surf_src->LockRect(&locked, nullptr, D3DLOCK_DISCARD); if (SUCCEEDED(hr)) { const char *rpixels = (const char*)data; int rpitch = psize * width; char *wpixels = (char*)locked.pBits; int wpitch = locked.Pitch; memcpy(wpixels, rpixels, data_size); surf_src->UnlockRect(); hr = m_device->UpdateSurface(surf_src, nullptr, surf_dst, nullptr); if (SUCCEEDED(hr)) { ret = true; } } surf_dst->Release(); }
bool fcGraphicsDeviceD3D9::readTexture(void *o_buf, size_t bufsize, void *tex_, int width, int height, fcTextureFormat format) { HRESULT hr; IDirect3DTexture9 *tex = (IDirect3DTexture9*)tex_; // D3D11 と同様 render target の内容は CPU からはアクセス不可能になっている。 // staging texture を用意してそれに内容を移し、CPU はそれ経由でデータを読む。 IDirect3DSurface9 *surf_dst = findOrCreateStagingTexture(width, height, format); if (surf_dst == nullptr) { return false; } IDirect3DSurface9* surf_src = nullptr; hr = tex->GetSurfaceLevel(0, &surf_src); if (FAILED(hr)){ return false; } bool ret = false; hr = m_device->GetRenderTargetData(surf_src, surf_dst); if (SUCCEEDED(hr)) { D3DLOCKED_RECT locked; hr = surf_dst->LockRect(&locked, nullptr, D3DLOCK_READONLY); if (SUCCEEDED(hr)) { char *wpixels = (char*)o_buf; int wpitch = width * fcGetPixelSize(format); const char *rpixels = (const char*)locked.pBits; int rpitch = locked.Pitch; // D3D11 と同様表向き解像度と内部解像度が違うケースを考慮 // (しかし、少なくとも手元の環境では常に wpitch == rpitch っぽい) if (wpitch == rpitch) { memcpy(wpixels, rpixels, bufsize); } else { for (int i = 0; i < height; ++i) { memcpy(wpixels, rpixels, wpitch); wpixels += wpitch; rpixels += rpitch; } } surf_dst->UnlockRect(); // D3D9 の ARGB32 のピクセルの並びは BGRA になっているので並べ替える if (format == fcTextureFormat_ARGB32) { BGRA_RGBA_conversion((RGBA<uint8_t>*)o_buf, bufsize / 4); } ret = true; } } surf_src->Release(); return ret; }
bool fcGraphicsDeviceD3D9::writeTexture(void *o_tex, int width, int height, fcTextureFormat format, const void *buf, size_t bufsize) { int psize = fcGetPixelSize(format); int pitch = psize * width; const size_t num_pixels = bufsize / psize; HRESULT hr; IDirect3DTexture9 *tex = (IDirect3DTexture9*)o_tex; // D3D11 と違い、D3D9 では書き込みも staging texture を経由する必要がある。 IDirect3DSurface9 *surf_src = findOrCreateStagingTexture(width, height, format); if (surf_src == nullptr) { return false; } IDirect3DSurface9* surf_dst = nullptr; hr = tex->GetSurfaceLevel(0, &surf_dst); if (FAILED(hr)){ return false; } bool ret = false; D3DLOCKED_RECT locked; hr = surf_src->LockRect(&locked, nullptr, D3DLOCK_DISCARD); if (SUCCEEDED(hr)) { const char *rpixels = (const char*)buf; int rpitch = psize * width; char *wpixels = (char*)locked.pBits; int wpitch = locked.Pitch; // こちらも ARGB32 の場合 BGRA に並べ替える必要がある if (format == fcTextureFormat_ARGB32) { copy_with_BGRA_RGBA_conversion((RGBA<uint8_t>*)wpixels, (RGBA<uint8_t>*)rpixels, bufsize / 4); } else { memcpy(wpixels, rpixels, bufsize); } surf_src->UnlockRect(); hr = m_device->UpdateSurface(surf_src, nullptr, surf_dst, nullptr); if (SUCCEEDED(hr)) { ret = true; } } surf_dst->Release(); return false; }
void CopyToTextureD3D9::copy(void *texptr, int width, int height, const void *dataptr, int data_num, DataConversion conv) { int psize = 16; int pitch = psize * width; int bufsize = data_num * psize; dataptr = getDataPointer(dataptr, data_num, width*height, conv, true); HRESULT hr; IDirect3DTexture9 *tex = (IDirect3DTexture9*)texptr; // D3D11 と違い、D3D9 では書き込みも staging texture を経由する必要がある。 IDirect3DSurface9 *surf_src = findOrCreateStagingTexture(width, height); if (surf_src == nullptr) { return; } IDirect3DSurface9* surf_dst = nullptr; hr = tex->GetSurfaceLevel(0, &surf_dst); if (FAILED(hr)) { return; } bool ret = false; D3DLOCKED_RECT locked; hr = surf_src->LockRect(&locked, nullptr, D3DLOCK_DISCARD); if (SUCCEEDED(hr)) { const char *rpixels = (const char*)dataptr; int rpitch = psize * width; char *wpixels = (char*)locked.pBits; int wpitch = locked.Pitch; memcpy(wpixels, rpixels, bufsize); surf_src->UnlockRect(); hr = m_device->UpdateSurface(surf_src, nullptr, surf_dst, nullptr); if (SUCCEEDED(hr)) { ret = true; } } surf_dst->Release(); }