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);
188 void SurfaceWin::drawPixel(int x, int y, unsigned int c, bool fastdraw)
190 //FixMe: locking for every single Pixel will be painfully slow
193 WaitForSingleObject(event,INFINITE); //since this might be called before surface
194 //allocation we will wait in this case, hopefully without deadlocks
196 return; //why does this happen
198 osd=((OsdWinPixel*)(Osd::getInstance()));
200 if (x>=swidth || y>=sheight) return; //do not draw outside the surface
202 //This should not happen!
207 osd->BeginPainting();
208 // D3DLOCKED_RECT lockrect;
209 RECT rect={x,y,x+1,y+1};
210 if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {
214 unsigned int*row=(unsigned int*)(((char*)lockrect.pBits));
216 if (d3dsurface->UnlockRect()!=D3D_OK) {
222 unsigned int*row=(unsigned int*)(((char*)lockrect.pBits+lockrect.Pitch*y+4*x));
230 void SurfaceWin::drawHorzLine(int x1, int x2, int y,const DrawStyle& c)
232 fillblt(x1, y, x2-x1, 1, c);
235 void SurfaceWin::drawVertLine(int x, int y1, int y2, const DrawStyle& c)
237 fillblt(x, y1, 1, y2-y1, c);
240 void SurfaceWin::drawBitmap(int x, int y, const Bitmap& bm,const DisplayRegion & region)
242 // Temporary code? Draw one pixel at a time using drawPixel()
244 for (UINT j = 0; j < bm.getHeight(); ++j)
245 for (UINT i = 0; i < bm.getWidth(); ++i)
246 drawPixel(x+i, y+j, bm.getColour(i,j),true);
250 int SurfaceWin::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME
252 WaitForSingleObject(event,INFINITE); //since this might be called before surface
253 //allocation we will wait in this case, hopefully without deadlocks
255 return 0; //why does this happen
257 OsdWinPixel* osd=((OsdWinPixel*)(Osd::getInstance()));
258 LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();
259 LPDIRECT3DSURFACE9 screensurface=((SurfaceWin*)screen)->getD3dsurface();
260 if (!screensurface) return 0;
261 RECT sourcerect={sx,sy,sx+w,sy+h};
262 POINT destpoint={dx,dy};
263 osd->BeginPainting();
264 if (d3ddev->UpdateSurface(d3dsurface,&sourcerect,screensurface,&destpoint)!=D3D_OK) {
265 Log::getInstance()->log("Surface", Log::DEBUG, "Could not update to Screen!");
273 int SurfaceWin::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)
275 //I don't see code using this function, so I skip it, since it is a MVP specific interface
279 void SurfaceWin::screenShot(const char* fileName)
281 //Isn't this for debugging only, so I won't implement it yet
284 void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
286 //Isn't this for debugging only, so I won't implement it yet
288 void SurfaceWin::ReleaseSurface()
291 LPDIRECT3DSURFACE9 temp_surf=d3dsurface;
292 LPDIRECT3DTEXTURE9 temp_text=d3dtexture;
296 if (temp_surf) temp_surf->Release();
297 if (temp_text) temp_text->Release();
300 void SurfaceWin::drawJpeg(const char *fileName, int x, int y, int *width, int *height){
301 WaitForSingleObject(event, INFINITE); //since this might be called before surface
302 //allocation we will wait in this case, hopefully without deadlocks
304 return; //why does this happen
306 OsdWinPixel* osd = ((OsdWinPixel*)(Osd::getInstance()));
307 osd->BeginPainting();
310 HRESULT hres = d3dsurface->GetDC(&dc);
311 if (hres != D3D_OK) return;
313 HRSRC hrc = FindResource(GetModuleHandle(NULL), fileName, RT_RCDATA);
314 DWORD size = SizeofResource(GetModuleHandle(NULL), hrc);
315 void *pointer = LockResource(LoadResource(GetModuleHandle(NULL),hrc));
316 HGLOBAL memhandle=GlobalAlloc(GMEM_MOVEABLE, size);
319 d3dsurface->ReleaseDC(dc);
323 void *mempointer = GlobalLock(memhandle);
325 d3dsurface->ReleaseDC(dc);
326 GlobalUnlock(mempointer);
327 GlobalFree(memhandle);
332 memcpy(mempointer, pointer, size);
336 IStream *memstream = NULL;
337 if (CreateStreamOnHGlobal(memhandle, FALSE, &memstream) != S_OK)
339 GlobalUnlock(mempointer);
340 GlobalFree(memhandle);
341 d3dsurface->ReleaseDC(dc);
347 Gdiplus::Graphics graphics(dc);
348 Gdiplus::Image image(memstream);
350 *width = image.GetWidth();
351 *height = image.GetHeight();
353 graphics.DrawImage(&image, x, y, *width, *height);
355 memstream->Release();
356 GlobalUnlock(mempointer);
357 GlobalFree(memhandle);
359 d3dsurface->ReleaseDC(dc);