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