]> git.vomp.tv Git - vompclient.git/blob - surfacewin.cc
Preparations for dynamic mode switching
[vompclient.git] / surfacewin.cc
1 /*\r
2     Copyright 2006 Marten Richter\r
3 \r
4     This file is part of VOMP.\r
5 \r
6     VOMP is free software; you can redistribute it and/or modify\r
7     it under the terms of the GNU General Public License as published by\r
8     the Free Software Foundation; either version 2 of the License, or\r
9     (at your option) any later version.\r
10 \r
11     VOMP is distributed in the hope that it will be useful,\r
12     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14     GNU General Public License for more details.\r
15 \r
16     You should have received a copy of the GNU General Public License\r
17     along with VOMP; if not, write to the Free Software\r
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.\r
19 */\r
20 \r
21 #include "surfacewin.h"\r
22 #include "osdwin.h"\r
23 #include "bitmap.h"\r
24 #include "log.h"\r
25 \r
26 SurfaceWin::SurfaceWin(int id)\r
27 : Surface(id)\r
28 {\r
29   d3dtexture=NULL;\r
30   d3dsurface=NULL;\r
31   sheight=swidth=0;\r
32 //  fastdraw=false;\r
33   event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL);\r
34 }\r
35 \r
36 SurfaceWin::~SurfaceWin()\r
37 {\r
38         if (d3dsurface) d3dsurface->Release();\r
39         if (d3dtexture) d3dtexture->Release();\r
40         CloseHandle(event);\r
41 }\r
42 \r
43 int SurfaceWin::create(UINT width, UINT height)\r
44 {\r
45         OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
46 \r
47 \r
48         LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();\r
49 \r
50         while (true) {\r
51                 if (screen==this) {\r
52                         osd->BeginPainting();\r
53                         if (d3ddev->CreateTexture(1024,1024,0,0,D3DFMT_A8R8G8B8,\r
54                                 // Does every adapter with alpha blending support this?\r
55                                 D3DPOOL_DEFAULT,&d3dtexture ,NULL)!=D3D_OK) {\r
56                                         osd->EndPainting();\r
57                                         MILLISLEEP(50);//wait maybe next time it will work\r
58                                         continue;\r
59                         }\r
60                         if (d3dtexture->GetSurfaceLevel(0,&d3dsurface)!=D3D_OK) {\r
61                                 d3dtexture->Release();\r
62                                 d3dtexture=NULL;\r
63                                 MILLISLEEP(50);\r
64                                 osd->EndPainting();\r
65                                 continue;\r
66                         }\r
67                 } else {\r
68                         HRESULT hres;\r
69                         if (hres=d3ddev->CreateOffscreenPlainSurface(width,height,D3DFMT_A8R8G8B8,\r
70                                 D3DPOOL_SYSTEMMEM,&d3dsurface,NULL)!=D3D_OK) {\r
71                                         osd->EndPainting();\r
72                                         MILLISLEEP(50);//wait maybe next time it will work\r
73 \r
74                                         continue;\r
75                         }\r
76 \r
77                 }\r
78                 osd->EndPainting();\r
79 \r
80                 sheight=height;\r
81                 swidth=width;\r
82                 /* If someone does high performance Animations on the OSD, we have to change the types\r
83                 of surface in order to address these performance issues, if we have only very few updates\r
84                 per second this would be fast enough !*/\r
85                 break;\r
86         }\r
87         SetEvent(event);\r
88         return 1;\r
89 }\r
90 \r
91 void SurfaceWin::display()\r
92 {\r
93 }\r
94 \r
95 int SurfaceWin::fillblt(int x, int y, int width, int height, const DrawStyle& c)\r
96 {\r
97   WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
98   //allocation we will wait in this case, hopefully without deadlocks\r
99   OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
100 \r
101   if (!d3dsurface) {\r
102     return 0; //why does this happen\r
103   }\r
104   ULONG col=c.rgba();\r
105 \r
106   LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();\r
107 \r
108   if (screen==this) {\r
109     //This should not happen!\r
110     return 0;\r
111 \r
112   } else {\r
113     osd->BeginPainting();\r
114     D3DLOCKED_RECT lockrect;\r
115     int cx,cy,cwidth,cheight;\r
116     cx=min(max(x,0),swidth-1);\r
117     cy=min(max(y,0),sheight-1);\r
118     cwidth=min(width,swidth-x);\r
119     cheight=min(height,sheight-y);\r
120     RECT rect={cx,cy,cwidth,cheight};\r
121 \r
122     if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {\r
123       return 0;\r
124     }\r
125     unsigned int line;\r
126     unsigned int column;\r
127     for (line=0;line<cheight;line++) {\r
128       unsigned int*row=((unsigned int*)(((char*)lockrect.pBits)+lockrect.Pitch*line));\r
129       for (column=0;column<cwidth;column++) {\r
130         row[column]=col;\r
131       }\r
132     }\r
133 \r
134     if (d3dsurface->UnlockRect()!=D3D_OK) {\r
135       osd->EndPainting();\r
136       return 0;\r
137     }\r
138     osd->EndPainting();\r
139   }\r
140 \r
141   return 0;\r
142 }\r
143 \r
144 \r
145 void SurfaceWin::startFastDraw(){\r
146     WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
147   //allocation we will wait in this case, hopefully without deadlocks\r
148   if (!d3dsurface) {\r
149     return; //why does this happen\r
150   }\r
151   OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
152   LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();\r
153   if (screen==this) {\r
154     //This should not happen!\r
155     return ;\r
156 \r
157   } else {\r
158     osd->BeginPainting();\r
159 //    D3DLOCKED_RECT lockrect;\r
160     RECT rect={0,0,swidth,sheight};\r
161     if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {\r
162       osd->EndPainting();\r
163       return ;\r
164     }\r
165   }\r
166 //  fastdraw=true;\r
167 }\r
168 void SurfaceWin::endFastDraw(){\r
169     OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
170     if (d3dsurface->UnlockRect()!=D3D_OK) {\r
171       osd->EndPainting();\r
172       return ;\r
173     }\r
174     osd->EndPainting();\r
175 //    fastdraw=false;\r
176  }\r
177 \r
178 void SurfaceWin::drawPixel(int x, int y, Colour & colour, bool fastdraw) {\r
179   int c = (  (0xFF000000         )\r
180              | (colour.red    << 16)\r
181              | (colour.green  <<  8)\r
182              | (colour.blue        ) );\r
183 \r
184     drawPixel(x, y, c, fastdraw);\r
185   }\r
186 \r
187 void SurfaceWin::drawPixel(int x, int y, unsigned int c, bool fastdraw)\r
188 {\r
189   //FixMe: locking for every single Pixel will be painfully slow\r
190     OsdWin* osd;\r
191     if (!fastdraw) {\r
192   WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
193   //allocation we will wait in this case, hopefully without deadlocks\r
194   if (!d3dsurface) {\r
195     return; //why does this happen\r
196   }\r
197          osd=((OsdWin*)(Osd::getInstance()));\r
198     }\r
199   if (x>=swidth || y>=sheight) return; //do not draw outside the surface\r
200   if (screen==this) {\r
201     //This should not happen!\r
202     return ;\r
203 \r
204   } else {\r
205       if (!fastdraw) {\r
206     osd->BeginPainting();\r
207 //        D3DLOCKED_RECT lockrect;\r
208     RECT rect={x,y,x+1,y+1};\r
209     if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {\r
210       osd->EndPainting();\r
211       return ;\r
212     }\r
213     unsigned int*row=(unsigned int*)(((char*)lockrect.pBits));\r
214     row[0]=c;\r
215     if (d3dsurface->UnlockRect()!=D3D_OK) {\r
216       osd->EndPainting();\r
217       return ;\r
218     }\r
219     osd->EndPainting();\r
220       } else {\r
221           unsigned int*row=(unsigned int*)(((char*)lockrect.pBits+lockrect.Pitch*y+4*x));\r
222           row[0]=c;\r
223       }\r
224 \r
225   }\r
226 \r
227 }\r
228 \r
229 void SurfaceWin::drawHorzLine(int x1, int x2, int y,const DrawStyle& c)\r
230 {\r
231    fillblt(x1, y, x2-x1, 1, c);\r
232 }\r
233 \r
234 void SurfaceWin::drawVertLine(int x, int y1, int y2, const DrawStyle& c)\r
235 {\r
236   fillblt(x, y1, 1, y2-y1, c);\r
237 }\r
238 \r
239 void SurfaceWin::drawBitmap(int x, int y, const Bitmap& bm)\r
240 {\r
241   // Temporary code? Draw one pixel at a time using drawPixel()\r
242   startFastDraw();\r
243   for (UINT j = 0; j < bm.getHeight(); ++j)\r
244     for (UINT i = 0; i < bm.getWidth(); ++i)\r
245       drawPixel(x+i, y+j, bm.getColour(i,j),true);\r
246   endFastDraw();\r
247 }\r
248 \r
249 int SurfaceWin::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME\r
250 {\r
251   WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
252   //allocation we will wait in this case, hopefully without deadlocks\r
253   if (!d3dsurface) {\r
254     return 0; //why does this happen\r
255   }\r
256   OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
257   LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();\r
258     LPDIRECT3DSURFACE9 screensurface=((SurfaceWin*)screen)->getD3dsurface();\r
259   if (!screensurface) return 0;\r
260   RECT sourcerect={sx,sy,sx+w,sy+h};\r
261   POINT destpoint={dx,dy};\r
262   osd->BeginPainting();\r
263   if (d3ddev->UpdateSurface(d3dsurface,&sourcerect,screensurface,&destpoint)!=D3D_OK) {\r
264     Log::getInstance()->log("Surface", Log::DEBUG, "Could not update to Screen!");\r
265     osd->EndPainting();\r
266     return 0;\r
267   }\r
268   osd->EndPainting();\r
269   return 0;\r
270 }\r
271 \r
272 int SurfaceWin::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)\r
273 {\r
274   //I don't see code using this function, so I skip it, since it is a MVP specific interface\r
275   return 0;\r
276 }\r
277 \r
278 void SurfaceWin::screenShot(const char* fileName)\r
279 {\r
280   //Isn't this for debugging only, so I won't implement it yet\r
281 }\r
282 \r
283 void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)\r
284 {\r
285   //Isn't this for debugging only, so I won't implement it yet\r
286 }\r
287 void SurfaceWin::ReleaseSurface()\r
288 {\r
289   ResetEvent(event);\r
290   LPDIRECT3DSURFACE9 temp_surf=d3dsurface;\r
291   LPDIRECT3DTEXTURE9 temp_text=d3dtexture;\r
292   d3dsurface=NULL;\r
293   d3dtexture=NULL;\r
294   sheight=swidth=0;\r
295   if (temp_surf) temp_surf->Release();\r
296   if (temp_text) temp_text->Release();\r
297 }\r
298 \r
299 void SurfaceWin::drawJpeg(const char *fileName,int x, int y,int *width, int *height){\r
300   WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
301   //allocation we will wait in this case, hopefully without deadlocks\r
302   if (!d3dsurface) {\r
303     return ; //why does this happen\r
304   }\r
305   OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
306 \r
307 \r
308   D3DXIMAGE_INFO image_inf;\r
309   osd->BeginPainting();\r
310 //  D3DXGetImageInfoFromFile(fileName,&image_inf);\r
311   D3DXGetImageInfoFromResource(NULL,fileName,&image_inf);\r
312   RECT dest_rec={x,y,x+image_inf.Width,\r
313     y+image_inf.Height};\r
314 /*  if (D3DXLoadSurfaceFromFile(\r
315     d3dsurface,\r
316     NULL,\r
317     &dest_rec,\r
318     fileName,\r
319     NULL,\r
320     D3DX_FILTER_NONE,\r
321     0,\r
322     &image_inf)!=D3D_OK) {\r
323       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");\r
324 \r
325   }*/\r
326   if (D3DXLoadSurfaceFromResource(\r
327     d3dsurface,\r
328     NULL,\r
329     &dest_rec,\r
330     NULL,\r
331     fileName,\r
332     NULL,\r
333     D3DX_FILTER_NONE,\r
334     0,\r
335     &image_inf)!=D3D_OK) {\r
336       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");\r
337 \r
338   }\r
339   osd->EndPainting();\r
340   *width=image_inf.Width;\r
341   *height=image_inf.Height;\r
342 \r
343 }\r
344 \r
345 /*\r
346 void SurfaceWin::drawJpeg(char *buffer,ULONG buflength,DWORD x, DWORD y,DWORD *width, DWORD *height){\r
347   WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
348   //allocation we will wait in this case, hopefully without deadlocks\r
349   if (!d3dsurface) {\r
350     return ; //why does this happen\r
351   }\r
352   OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
353 \r
354 \r
355   D3DXIMAGE_INFO image_inf;\r
356   osd->BeginPainting();\r
357 //  D3DXGetImageInfoFromFile(fileName,&image_inf);\r
358   D3DXGetImageInfoFromFileInMemory((void*)buffer,buflength,&image_inf);\r
359   RECT dest_rec={x,y,x+image_inf.Width,\r
360     y+image_inf.Height};\r
361 /*  if (D3DXLoadSurfaceFromFile(\r
362     d3dsurface,\r
363     NULL,\r
364     &dest_rec,\r
365     fileName,\r
366     NULL,\r
367     D3DX_FILTER_NONE,\r
368     0,\r
369     &image_inf)!=D3D_OK) {\r
370       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");\r
371 \r
372   }*/\r
373 /*  if (D3DXLoadSurfaceFromResource(\r
374     d3dsurface,\r
375     NULL,\r
376     &dest_rec,\r
377     NULL,\r
378     fileName,\r
379     NULL,\r
380     D3DX_FILTER_NONE,\r
381     0,\r
382     &image_inf)!=D3D_OK) {\r
383       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");\r
384 \r
385   }*\r
386   if (D3DXLoadSurfaceFromFileInMemory(\r
387     d3dsurface,\r
388     NULL,\r
389     &dest_rec,\r
390     (void*)buffer,\r
391     buflength,\r
392     NULL,\r
393     D3DX_FILTER_NONE,\r
394     0,\r
395     &image_inf)!=D3D_OK) {\r
396       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");\r
397 \r
398   }\r
399   osd->EndPainting();\r
400   *width=image_inf.Width;\r
401   *height=image_inf.Height;\r
402 \r
403 }*/\r
404 \r