]> git.vomp.tv Git - vompclient-marten.git/blob - surfacewin.cc
Motion Compensation, all implemented, all buggy
[vompclient-marten.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, unsigned int 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 \r
105   LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();\r
106 \r
107   if (screen==this) {\r
108     //This should not happen!\r
109     return 0;\r
110 \r
111   } else {\r
112     osd->BeginPainting();\r
113     D3DLOCKED_RECT lockrect;\r
114     int cx,cy,cwidth,cheight;\r
115     cx=min(max(x,0),swidth-1);\r
116     cy=min(max(y,0),sheight-1);\r
117     cwidth=min(width,swidth-x);\r
118     cheight=min(height,sheight-y);\r
119     RECT rect={cx,cy,cwidth,cheight};\r
120 \r
121     if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {\r
122       return 0;\r
123     }\r
124     unsigned int line;\r
125     unsigned int column;\r
126     for (line=0;line<cheight;line++) {\r
127       unsigned int*row=((unsigned int*)(((char*)lockrect.pBits)+lockrect.Pitch*line));\r
128       for (column=0;column<cwidth;column++) {\r
129         row[column]=c;\r
130       }\r
131     }\r
132 \r
133     if (d3dsurface->UnlockRect()!=D3D_OK) {\r
134       osd->EndPainting();\r
135       return 0;\r
136     }\r
137     osd->EndPainting();\r
138   }\r
139 \r
140   return 0;\r
141 }\r
142 \r
143 \r
144 void SurfaceWin::startFastDraw(){\r
145     WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
146   //allocation we will wait in this case, hopefully without deadlocks\r
147   if (!d3dsurface) {\r
148     return; //why does this happen\r
149   }\r
150   OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
151   LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();\r
152   if (screen==this) {\r
153     //This should not happen!\r
154     return ;\r
155 \r
156   } else {\r
157     osd->BeginPainting();\r
158 //    D3DLOCKED_RECT lockrect;\r
159     RECT rect={0,0,swidth,sheight};\r
160     if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {\r
161       osd->EndPainting();\r
162       return ;\r
163     }\r
164   }\r
165 //  fastdraw=true;\r
166 }\r
167 void SurfaceWin::endFastDraw(){\r
168     OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
169     if (d3dsurface->UnlockRect()!=D3D_OK) {\r
170       osd->EndPainting();\r
171       return ;\r
172     }\r
173     osd->EndPainting();\r
174 //    fastdraw=false;\r
175  }\r
176 \r
177 void SurfaceWin::drawPixel(int x, int y, Colour & colour, bool fastdraw) {\r
178   int c = (  (0xFF000000         )\r
179              | (colour.red    << 16)\r
180              | (colour.green  <<  8)\r
181              | (colour.blue        ) );\r
182 \r
183     drawPixel(x, y, c, fastdraw);\r
184   }\r
185 \r
186 void SurfaceWin::drawPixel(int x, int y, unsigned int c, bool fastdraw)\r
187 {\r
188   //FixMe: locking for every single Pixel will be painfully slow\r
189     OsdWin* osd;\r
190     if (!fastdraw) {\r
191   WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
192   //allocation we will wait in this case, hopefully without deadlocks\r
193   if (!d3dsurface) {\r
194     return; //why does this happen\r
195   }\r
196          osd=((OsdWin*)(Osd::getInstance()));\r
197     }\r
198   if (x>=swidth || y>=sheight) return; //do not draw outside the surface\r
199   if (screen==this) {\r
200     //This should not happen!\r
201     return ;\r
202 \r
203   } else {\r
204       if (!fastdraw) {\r
205     osd->BeginPainting();\r
206 //        D3DLOCKED_RECT lockrect;\r
207     RECT rect={x,y,x+1,y+1};\r
208     if (d3dsurface->LockRect(&lockrect,&rect,D3DLOCK_DISCARD)!=D3D_OK) {\r
209       osd->EndPainting();\r
210       return ;\r
211     }\r
212     unsigned int*row=(unsigned int*)(((char*)lockrect.pBits));\r
213     row[0]=c;\r
214     if (d3dsurface->UnlockRect()!=D3D_OK) {\r
215       osd->EndPainting();\r
216       return ;\r
217     }\r
218     osd->EndPainting();\r
219       } else {\r
220           unsigned int*row=(unsigned int*)(((char*)lockrect.pBits+lockrect.Pitch*y+4*x));\r
221           row[0]=c;\r
222       }\r
223 \r
224   }\r
225 \r
226 }\r
227 \r
228 void SurfaceWin::drawHorzLine(int x1, int x2, int y, unsigned int c)\r
229 {\r
230    fillblt(x1, y, x2-x1, 1, c);\r
231 }\r
232 \r
233 void SurfaceWin::drawVertLine(int x, int y1, int y2, unsigned int c)\r
234 {\r
235   fillblt(x, y1, 1, y2-y1, c);\r
236 }\r
237 \r
238 void SurfaceWin::drawBitmap(int x, int y, const Bitmap& bm)\r
239 {\r
240   // Temporary code? Draw one pixel at a time using drawPixel()\r
241   startFastDraw();\r
242   for (UINT j = 0; j < bm.getHeight(); ++j)\r
243     for (UINT i = 0; i < bm.getWidth(); ++i)\r
244       drawPixel(x+i, y+j, bm.getColour(i,j),true);\r
245   endFastDraw();\r
246 }\r
247 \r
248 int SurfaceWin::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME\r
249 {\r
250   WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
251   //allocation we will wait in this case, hopefully without deadlocks\r
252   if (!d3dsurface) {\r
253     return 0; //why does this happen\r
254   }\r
255   OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
256   LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();\r
257     LPDIRECT3DSURFACE9 screensurface=((SurfaceWin*)screen)->getD3dsurface();\r
258   if (!screensurface) return 0;\r
259   RECT sourcerect={sx,sy,sx+w,sy+h};\r
260   POINT destpoint={dx,dy};\r
261   osd->BeginPainting();\r
262   if (d3ddev->UpdateSurface(d3dsurface,&sourcerect,screensurface,&destpoint)!=D3D_OK) {\r
263     Log::getInstance()->log("Surface", Log::DEBUG, "Could not update to Screen!");\r
264     osd->EndPainting();\r
265     return 0;\r
266   }\r
267   osd->EndPainting();\r
268   return 0;\r
269 }\r
270 \r
271 int SurfaceWin::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)\r
272 {\r
273   //I don't see code using this function, so I skip it, since it is a MVP specific interface\r
274   return 0;\r
275 }\r
276 \r
277 void SurfaceWin::screenShot(const char* fileName)\r
278 {\r
279   //Isn't this for debugging only, so I won't implement it yet\r
280 }\r
281 \r
282 void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)\r
283 {\r
284   //Isn't this for debugging only, so I won't implement it yet\r
285 }\r
286 void SurfaceWin::ReleaseSurface()\r
287 {\r
288   ResetEvent(event);\r
289   LPDIRECT3DSURFACE9 temp_surf=d3dsurface;\r
290   LPDIRECT3DTEXTURE9 temp_text=d3dtexture;\r
291   d3dsurface=NULL;\r
292   d3dtexture=NULL;\r
293   sheight=swidth=0;\r
294   if (temp_surf) temp_surf->Release();\r
295   if (temp_text) temp_text->Release();\r
296 }\r
297 \r
298 void SurfaceWin::drawJpeg(const char *fileName,int x, int y,int *width, int *height){\r
299   WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
300   //allocation we will wait in this case, hopefully without deadlocks\r
301   if (!d3dsurface) {\r
302     return ; //why does this happen\r
303   }\r
304   OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
305 \r
306 \r
307   D3DXIMAGE_INFO image_inf;\r
308   osd->BeginPainting();\r
309 //  D3DXGetImageInfoFromFile(fileName,&image_inf);\r
310   D3DXGetImageInfoFromResource(NULL,fileName,&image_inf);\r
311   RECT dest_rec={x,y,x+image_inf.Width,\r
312     y+image_inf.Height};\r
313 /*  if (D3DXLoadSurfaceFromFile(\r
314     d3dsurface,\r
315     NULL,\r
316     &dest_rec,\r
317     fileName,\r
318     NULL,\r
319     D3DX_FILTER_NONE,\r
320     0,\r
321     &image_inf)!=D3D_OK) {\r
322       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");\r
323 \r
324   }*/\r
325   if (D3DXLoadSurfaceFromResource(\r
326     d3dsurface,\r
327     NULL,\r
328     &dest_rec,\r
329     NULL,\r
330     fileName,\r
331     NULL,\r
332     D3DX_FILTER_NONE,\r
333     0,\r
334     &image_inf)!=D3D_OK) {\r
335       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");\r
336 \r
337   }\r
338   osd->EndPainting();\r
339   *width=image_inf.Width;\r
340   *height=image_inf.Height;\r
341 \r
342 }\r
343 \r
344 /*\r
345 void SurfaceWin::drawJpeg(char *buffer,ULONG buflength,DWORD x, DWORD y,DWORD *width, DWORD *height){\r
346   WaitForSingleObject(event,INFINITE); //since this might be called before surface\r
347   //allocation we will wait in this case, hopefully without deadlocks\r
348   if (!d3dsurface) {\r
349     return ; //why does this happen\r
350   }\r
351   OsdWin* osd=((OsdWin*)(Osd::getInstance()));\r
352 \r
353 \r
354   D3DXIMAGE_INFO image_inf;\r
355   osd->BeginPainting();\r
356 //  D3DXGetImageInfoFromFile(fileName,&image_inf);\r
357   D3DXGetImageInfoFromFileInMemory((void*)buffer,buflength,&image_inf);\r
358   RECT dest_rec={x,y,x+image_inf.Width,\r
359     y+image_inf.Height};\r
360 /*  if (D3DXLoadSurfaceFromFile(\r
361     d3dsurface,\r
362     NULL,\r
363     &dest_rec,\r
364     fileName,\r
365     NULL,\r
366     D3DX_FILTER_NONE,\r
367     0,\r
368     &image_inf)!=D3D_OK) {\r
369       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");\r
370 \r
371   }*/\r
372 /*  if (D3DXLoadSurfaceFromResource(\r
373     d3dsurface,\r
374     NULL,\r
375     &dest_rec,\r
376     NULL,\r
377     fileName,\r
378     NULL,\r
379     D3DX_FILTER_NONE,\r
380     0,\r
381     &image_inf)!=D3D_OK) {\r
382       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");\r
383 \r
384   }*\r
385   if (D3DXLoadSurfaceFromFileInMemory(\r
386     d3dsurface,\r
387     NULL,\r
388     &dest_rec,\r
389     (void*)buffer,\r
390     buflength,\r
391     NULL,\r
392     D3DX_FILTER_NONE,\r
393     0,\r
394     &image_inf)!=D3D_OK) {\r
395       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");\r
396 \r
397   }\r
398   osd->EndPainting();\r
399   *width=image_inf.Width;\r
400   *height=image_inf.Height;\r
401 \r
402 }*/\r
403 \r