2 Copyright 2006 Marten Richter
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "surfacewin.h"
22 #include "osdwinpixel.h"
27 SurfaceWin::SurfaceWin(int id)
34 event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL);
37 SurfaceWin::~SurfaceWin()
39 if (d3dsurface) d3dsurface->Release();
40 if (d3dtexture) d3dtexture->Release();
44 int SurfaceWin::create(UINT width, UINT height)
46 OsdWinPixel* osd=((OsdWinPixel*)(Osd::getInstance()));
49 LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();
54 if (d3ddev->CreateTexture(1024,1024,0,0,D3DFMT_A8R8G8B8,
55 // Does every adapter with alpha blending support this?
56 D3DPOOL_DEFAULT,&d3dtexture ,NULL)!=D3D_OK) {
58 MILLISLEEP(50);//wait maybe next time it will work
61 if (d3dtexture->GetSurfaceLevel(0,&d3dsurface)!=D3D_OK) {
62 d3dtexture->Release();
70 if (hres=d3ddev->CreateOffscreenPlainSurface(width,height,D3DFMT_A8R8G8B8,
71 D3DPOOL_SYSTEMMEM,&d3dsurface,NULL)!=D3D_OK) {
73 MILLISLEEP(50);//wait maybe next time it will work
83 /* If someone does high performance Animations on the OSD, we have to change the types
84 of surface in order to address these performance issues, if we have only very few updates
85 per second this would be fast enough !*/
92 void SurfaceWin::display()
96 int SurfaceWin::fillblt(int x, int y, int width, int height, const DrawStyle& c)
98 WaitForSingleObject(event,INFINITE); //since this might be called before surface
99 //allocation we will wait in this case, hopefully without deadlocks
100 OsdWinPixel* osd=((OsdWinPixel*)(Osd::getInstance()));
103 return 0; //why does this happen
107 LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();
110 //This should not happen!
114 osd->BeginPainting();
115 D3DLOCKED_RECT lockrect;
116 int cx,cy,cwidth,cheight;
117 cx=min(max(x,0),swidth-1);
118 cy=min(max(y,0),sheight-1);
119 cwidth=min(width,swidth-x);
120 cheight=min(height,sheight-y);
121 RECT rect={cx,cy,cwidth,cheight};
123 if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {
128 for (line=0;line<cheight;line++) {
129 unsigned int*row=((unsigned int*)(((char*)lockrect.pBits)+lockrect.Pitch*line));
130 for (column=0;column<cwidth;column++) {
135 if (d3dsurface->UnlockRect()!=D3D_OK) {
146 void SurfaceWin::startFastDraw(){
147 WaitForSingleObject(event,INFINITE); //since this might be called before surface
148 //allocation we will wait in this case, hopefully without deadlocks
150 return; //why does this happen
152 OsdWinPixel* osd=((OsdWinPixel*)(Osd::getInstance()));
153 LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();
155 //This should not happen!
159 osd->BeginPainting();
160 // D3DLOCKED_RECT lockrect;
161 RECT rect={0,0,swidth,sheight};
162 if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {
169 void SurfaceWin::endFastDraw(){
170 OsdWinPixel* osd=((OsdWinPixel*)(Osd::getInstance()));
171 if (d3dsurface->UnlockRect()!=D3D_OK) {
179 void SurfaceWin::drawPixel(int x, int y, Colour & colour, bool fastdraw) {
180 int c = ( (0xFF000000 )
182 | (colour.green << 8)
185 drawPixel(x, y, c, fastdraw);
190 #pragma warning(disable : 4703)
193 void SurfaceWin::drawPixel(int x, int y, unsigned int c, bool fastdraw)
195 //FixMe: locking for every single Pixel will be painfully slow
198 WaitForSingleObject(event,INFINITE); //since this might be called before surface
199 //allocation we will wait in this case, hopefully without deadlocks
201 return; //why does this happen
203 osd=((OsdWinPixel*)(Osd::getInstance()));
205 if (x>=swidth || y>=sheight) return; //do not draw outside the surface
207 //This should not happen!
212 osd->BeginPainting();
213 // D3DLOCKED_RECT lockrect;
214 RECT rect={x,y,x+1,y+1};
215 if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {
219 unsigned int*row=(unsigned int*)(((char*)lockrect.pBits));
221 if (d3dsurface->UnlockRect()!=D3D_OK) {
227 unsigned int*row=(unsigned int*)(((char*)lockrect.pBits+lockrect.Pitch*y+4*x));
235 void SurfaceWin::drawHorzLine(int x1, int x2, int y,const DrawStyle& c)
237 fillblt(x1, y, x2-x1, 1, c);
240 void SurfaceWin::drawVertLine(int x, int y1, int y2, const DrawStyle& c)
242 fillblt(x, y1, 1, y2-y1, c);
245 void SurfaceWin::drawBitmap(int x, int y, const Bitmap& bm,const DisplayRegion & region)
247 // Temporary code? Draw one pixel at a time using drawPixel()
249 for (UINT j = 0; j < bm.getHeight(); ++j)
250 for (UINT i = 0; i < bm.getWidth(); ++i)
251 drawPixel(x+i, y+j, bm.getColour(i,j),true);
255 int SurfaceWin::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME
257 WaitForSingleObject(event,INFINITE); //since this might be called before surface
258 //allocation we will wait in this case, hopefully without deadlocks
260 return 0; //why does this happen
262 OsdWinPixel* osd=((OsdWinPixel*)(Osd::getInstance()));
263 LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();
264 LPDIRECT3DSURFACE9 screensurface=((SurfaceWin*)screen)->getD3dsurface();
265 if (!screensurface) return 0;
266 RECT sourcerect={sx,sy,sx+w,sy+h};
267 POINT destpoint={dx,dy};
268 osd->BeginPainting();
269 if (d3ddev->UpdateSurface(d3dsurface,&sourcerect,screensurface,&destpoint)!=D3D_OK) {
270 Log::getInstance()->log("Surface", Log::DEBUG, "Could not update to Screen!");
278 int SurfaceWin::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)
280 //I don't see code using this function, so I skip it, since it is a MVP specific interface
284 void SurfaceWin::screenShot(const char* fileName)
286 //Isn't this for debugging only, so I won't implement it yet
289 void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
291 //Isn't this for debugging only, so I won't implement it yet
293 void SurfaceWin::ReleaseSurface()
296 LPDIRECT3DSURFACE9 temp_surf=d3dsurface;
297 LPDIRECT3DTEXTURE9 temp_text=d3dtexture;
301 if (temp_surf) temp_surf->Release();
302 if (temp_text) temp_text->Release();
305 void SurfaceWin::drawJpeg(const char *fileName, int x, int y, int *width, int *height){
306 WaitForSingleObject(event, INFINITE); //since this might be called before surface
307 //allocation we will wait in this case, hopefully without deadlocks
309 return; //why does this happen
311 OsdWinPixel* osd = ((OsdWinPixel*)(Osd::getInstance()));
312 osd->BeginPainting();
315 HRESULT hres = d3dsurface->GetDC(&dc);
316 if (hres != D3D_OK) return;
318 HRSRC hrc = FindResource(GetModuleHandle(NULL), fileName, RT_RCDATA);
319 DWORD size = SizeofResource(GetModuleHandle(NULL), hrc);
320 void *pointer = LockResource(LoadResource(GetModuleHandle(NULL),hrc));
321 HGLOBAL memhandle=GlobalAlloc(GMEM_MOVEABLE, size);
324 d3dsurface->ReleaseDC(dc);
328 void *mempointer = GlobalLock(memhandle);
330 d3dsurface->ReleaseDC(dc);
331 GlobalUnlock(mempointer);
332 GlobalFree(memhandle);
337 memcpy(mempointer, pointer, size);
341 IStream *memstream = NULL;
342 if (CreateStreamOnHGlobal(memhandle, FALSE, &memstream) != S_OK)
344 GlobalUnlock(mempointer);
345 GlobalFree(memhandle);
346 d3dsurface->ReleaseDC(dc);
352 Gdiplus::Graphics graphics(dc);
353 Gdiplus::Image image(memstream);
355 *width = image.GetWidth();
356 *height = image.GetHeight();
358 graphics.DrawImage(&image, x, y, *width, *height);
360 memstream->Release();
361 GlobalUnlock(mempointer);
362 GlobalFree(memhandle);
364 d3dsurface->ReleaseDC(dc);