]> git.vomp.tv Git - vompclient.git/blob - surfacewin.cc
Bitmap and VPictureBanner CWFs
[vompclient.git] / surfacewin.cc
1 /*
2     Copyright 2006 Marten Richter
3
4     This file is part of VOMP.
5
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.
10
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.
15
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.
19 */
20
21 #include "surfacewin.h"
22 #include "osdwinpixel.h"
23 #include "bitmap.h"
24 #include "log.h"
25 #include <gdiplus.h>
26
27 SurfaceWin::SurfaceWin(int id)
28 : Surface(id)
29 {
30   d3dtexture=NULL;
31   d3dsurface=NULL;
32   sheight=swidth=0;
33 //  fastdraw=false;
34   event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL);
35 }
36
37 SurfaceWin::~SurfaceWin()
38 {
39         if (d3dsurface) d3dsurface->Release();
40         if (d3dtexture) d3dtexture->Release();
41         CloseHandle(event);
42 }
43
44 int SurfaceWin::create(UINT width, UINT height)
45 {
46         OsdWinPixel* osd=((OsdWinPixel*)(Osd::getInstance()));
47
48
49         LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();
50
51         while (true) {
52                 if (screen==this) {
53                         osd->BeginPainting();
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) {
57                                         osd->EndPainting();
58                                         MILLISLEEP(50);//wait maybe next time it will work
59                                         continue;
60                         }
61                         if (d3dtexture->GetSurfaceLevel(0,&d3dsurface)!=D3D_OK) {
62                                 d3dtexture->Release();
63                                 d3dtexture=NULL;
64                                 MILLISLEEP(50);
65                                 osd->EndPainting();
66                                 continue;
67                         }
68                 } else {
69                         HRESULT hres;
70                         if (hres=d3ddev->CreateOffscreenPlainSurface(width,height,D3DFMT_A8R8G8B8,
71                                 D3DPOOL_SYSTEMMEM,&d3dsurface,NULL)!=D3D_OK) {
72                                         osd->EndPainting();
73                                         MILLISLEEP(50);//wait maybe next time it will work
74
75                                         continue;
76                         }
77
78                 }
79                 osd->EndPainting();
80
81                 sheight=height;
82                 swidth=width;
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 !*/
86                 break;
87         }
88         SetEvent(event);
89         return 1;
90 }
91
92 void SurfaceWin::display()
93 {
94 }
95
96 int SurfaceWin::fillblt(int x, int y, int width, int height, const DrawStyle& c)
97 {
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()));
101
102   if (!d3dsurface) {
103     return 0; //why does this happen
104   }
105   ULONG col=c.rgba();
106
107   LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();
108
109   if (screen==this) {
110     //This should not happen!
111     return 0;
112
113   } else {
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};
122
123     if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {
124       return 0;
125     }
126     unsigned int line;
127     unsigned int column;
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++) {
131         row[column]=col;
132       }
133     }
134
135     if (d3dsurface->UnlockRect()!=D3D_OK) {
136       osd->EndPainting();
137       return 0;
138     }
139     osd->EndPainting();
140   }
141
142   return 0;
143 }
144
145
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
149   if (!d3dsurface) {
150     return; //why does this happen
151   }
152   OsdWinPixel* osd=((OsdWinPixel*)(Osd::getInstance()));
153   LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();
154   if (screen==this) {
155     //This should not happen!
156     return ;
157
158   } else {
159     osd->BeginPainting();
160 //    D3DLOCKED_RECT lockrect;
161     RECT rect={0,0,swidth,sheight};
162     if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {
163       osd->EndPainting();
164       return ;
165     }
166   }
167 //  fastdraw=true;
168 }
169 void SurfaceWin::endFastDraw(){
170     OsdWinPixel* osd=((OsdWinPixel*)(Osd::getInstance()));
171     if (d3dsurface->UnlockRect()!=D3D_OK) {
172       osd->EndPainting();
173       return ;
174     }
175     osd->EndPainting();
176 //    fastdraw=false;
177  }
178
179 void SurfaceWin::drawPixel(int x, int y, Colour & colour, bool fastdraw) {
180   int c = (  (0xFF000000         )
181              | (colour.red    << 16)
182              | (colour.green  <<  8)
183              | (colour.blue        ) );
184
185     drawPixel(x, y, c, fastdraw);
186   }
187
188 #if WIN32
189 // FIXME win pragma
190 #pragma warning(disable : 4703)
191 #endif
192
193 void SurfaceWin::drawPixel(int x, int y, unsigned int c, bool fastdraw)
194 {
195   //FixMe: locking for every single Pixel will be painfully slow
196     OsdWinPixel* osd;
197     if (!fastdraw) {
198   WaitForSingleObject(event,INFINITE); //since this might be called before surface
199   //allocation we will wait in this case, hopefully without deadlocks
200   if (!d3dsurface) {
201     return; //why does this happen
202   }
203          osd=((OsdWinPixel*)(Osd::getInstance()));
204     }
205   if (x>=swidth || y>=sheight) return; //do not draw outside the surface
206   if (screen==this) {
207     //This should not happen!
208     return ;
209
210   } else {
211       if (!fastdraw) {
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) {
216       osd->EndPainting();
217       return ;
218     }
219     unsigned int*row=(unsigned int*)(((char*)lockrect.pBits));
220     row[0]=c;
221     if (d3dsurface->UnlockRect()!=D3D_OK) {
222       osd->EndPainting();
223       return ;
224     }
225     osd->EndPainting();
226       } else {
227           unsigned int*row=(unsigned int*)(((char*)lockrect.pBits+lockrect.Pitch*y+4*x));
228           row[0]=c;
229       }
230
231   }
232
233 }
234
235 void SurfaceWin::drawHorzLine(int x1, int x2, int y,const DrawStyle& c)
236 {
237    fillblt(x1, y, x2-x1, 1, c);
238 }
239
240 void SurfaceWin::drawVertLine(int x, int y1, int y2, const DrawStyle& c)
241 {
242   fillblt(x, y1, 1, y2-y1, c);
243 }
244
245 void SurfaceWin::drawBitmap(int x, int y, const Bitmap& bm,const DisplayRegion & region)
246 {
247   // Temporary code? Draw one pixel at a time using drawPixel()
248   startFastDraw();
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);
252   endFastDraw();
253 }
254
255 int SurfaceWin::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME
256 {
257   WaitForSingleObject(event,INFINITE); //since this might be called before surface
258   //allocation we will wait in this case, hopefully without deadlocks
259   if (!d3dsurface) {
260     return 0; //why does this happen
261   }
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!");
271     osd->EndPainting();
272     return 0;
273   }
274   osd->EndPainting();
275   return 0;
276 }
277
278 int SurfaceWin::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)
279 {
280   //I don't see code using this function, so I skip it, since it is a MVP specific interface
281   return 0;
282 }
283
284 bool SurfaceWin::screenShot(const char* fileName)
285 {
286   //Isn't this for debugging only, so I won't implement it yet
287   return false;
288 }
289
290 void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
291 {
292   //Isn't this for debugging only, so I won't implement it yet
293 }
294 void SurfaceWin::ReleaseSurface()
295 {
296   ResetEvent(event);
297   LPDIRECT3DSURFACE9 temp_surf=d3dsurface;
298   LPDIRECT3DTEXTURE9 temp_text=d3dtexture;
299   d3dsurface=NULL;
300   d3dtexture=NULL;
301   sheight=swidth=0;
302   if (temp_surf) temp_surf->Release();
303   if (temp_text) temp_text->Release();
304 }
305
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
309         if (!d3dsurface) {
310                 return; //why does this happen
311         }
312         OsdWinPixel* osd = ((OsdWinPixel*)(Osd::getInstance()));
313         osd->BeginPainting();
314
315         HDC dc;
316         HRESULT hres = d3dsurface->GetDC(&dc);
317         if (hres != D3D_OK) return; 
318
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);
323         if (!memhandle)
324         {
325                 d3dsurface->ReleaseDC(dc);
326                 UnlockResource(hrc);
327                 return;
328         }
329         void *mempointer = GlobalLock(memhandle);
330         if (!mempointer) {
331                 d3dsurface->ReleaseDC(dc);
332                 GlobalUnlock(mempointer);
333                 GlobalFree(memhandle);
334                 UnlockResource(hrc);
335                 return;
336         }
337         
338         memcpy(mempointer, pointer, size);
339         UnlockResource(hrc);
340
341
342         IStream *memstream = NULL;
343         if (CreateStreamOnHGlobal(memhandle, FALSE, &memstream) != S_OK)
344         {
345                 GlobalUnlock(mempointer);
346                 GlobalFree(memhandle);
347                 d3dsurface->ReleaseDC(dc);
348                 
349                 return;
350         } 
351
352
353         Gdiplus::Graphics graphics(dc);
354         Gdiplus::Image image(memstream);
355         
356         *width = image.GetWidth();
357         *height = image.GetHeight();
358
359         graphics.DrawImage(&image, x, y, *width, *height);
360
361         memstream->Release();
362         GlobalUnlock(mempointer);
363         GlobalFree(memhandle);
364         
365         d3dsurface->ReleaseDC(dc);
366         osd->EndPainting();
367
368
369 }
370
371
372