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 bool SurfaceWin::screenShot(const char* fileName)
286 //Isn't this for debugging only, so I won't implement it yet
290 void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
292 //Isn't this for debugging only, so I won't implement it yet
294 void SurfaceWin::ReleaseSurface()
297 LPDIRECT3DSURFACE9 temp_surf=d3dsurface;
298 LPDIRECT3DTEXTURE9 temp_text=d3dtexture;
302 if (temp_surf) temp_surf->Release();
303 if (temp_text) temp_text->Release();
306 void SurfaceWin::drawJpeg(const char *fileName, int x, int y, int *width, int *height){
307 WaitForSingleObject(event, INFINITE); //since this might be called before surface
308 //allocation we will wait in this case, hopefully without deadlocks
310 return; //why does this happen
312 OsdWinPixel* osd = ((OsdWinPixel*)(Osd::getInstance()));
313 osd->BeginPainting();
316 HRESULT hres = d3dsurface->GetDC(&dc);
317 if (hres != D3D_OK) return;
319 HRSRC hrc = FindResource(GetModuleHandle(NULL), fileName, RT_RCDATA);
320 DWORD size = SizeofResource(GetModuleHandle(NULL), hrc);
321 void *pointer = LockResource(LoadResource(GetModuleHandle(NULL),hrc));
322 HGLOBAL memhandle=GlobalAlloc(GMEM_MOVEABLE, size);
325 d3dsurface->ReleaseDC(dc);
329 void *mempointer = GlobalLock(memhandle);
331 d3dsurface->ReleaseDC(dc);
332 GlobalUnlock(mempointer);
333 GlobalFree(memhandle);
338 memcpy(mempointer, pointer, size);
342 IStream *memstream = NULL;
343 if (CreateStreamOnHGlobal(memhandle, FALSE, &memstream) != S_OK)
345 GlobalUnlock(mempointer);
346 GlobalFree(memhandle);
347 d3dsurface->ReleaseDC(dc);
353 Gdiplus::Graphics graphics(dc);
354 Gdiplus::Image image(memstream);
356 *width = image.GetWidth();
357 *height = image.GetHeight();
359 graphics.DrawImage(&image, x, y, *width, *height);
361 memstream->Release();
362 GlobalUnlock(mempointer);
363 GlobalFree(memhandle);
365 d3dsurface->ReleaseDC(dc);