]> git.vomp.tv Git - vompclient.git/blob - surfacewin.cc
dvbsubtitles fixup part 2
[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 #include <D3dx9tex.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         OsdWin* osd=((OsdWin*)(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   OsdWin* osd=((OsdWin*)(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   OsdWin* osd=((OsdWin*)(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     OsdWin* osd=((OsdWin*)(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 void SurfaceWin::drawPixel(int x, int y, unsigned int c, bool fastdraw)
189 {
190   //FixMe: locking for every single Pixel will be painfully slow
191     OsdWin* osd;
192     if (!fastdraw) {
193   WaitForSingleObject(event,INFINITE); //since this might be called before surface
194   //allocation we will wait in this case, hopefully without deadlocks
195   if (!d3dsurface) {
196     return; //why does this happen
197   }
198          osd=((OsdWin*)(Osd::getInstance()));
199     }
200   if (x>=swidth || y>=sheight) return; //do not draw outside the surface
201   if (screen==this) {
202     //This should not happen!
203     return ;
204
205   } else {
206       if (!fastdraw) {
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) {
211       osd->EndPainting();
212       return ;
213     }
214     unsigned int*row=(unsigned int*)(((char*)lockrect.pBits));
215     row[0]=c;
216     if (d3dsurface->UnlockRect()!=D3D_OK) {
217       osd->EndPainting();
218       return ;
219     }
220     osd->EndPainting();
221       } else {
222           unsigned int*row=(unsigned int*)(((char*)lockrect.pBits+lockrect.Pitch*y+4*x));
223           row[0]=c;
224       }
225
226   }
227
228 }
229
230 void SurfaceWin::drawHorzLine(int x1, int x2, int y,const DrawStyle& c)
231 {
232    fillblt(x1, y, x2-x1, 1, c);
233 }
234
235 void SurfaceWin::drawVertLine(int x, int y1, int y2, const DrawStyle& c)
236 {
237   fillblt(x, y1, 1, y2-y1, c);
238 }
239
240 void SurfaceWin::drawBitmap(int x, int y, const Bitmap& bm,const DisplayRegion & region)
241 {
242   // Temporary code? Draw one pixel at a time using drawPixel()
243   startFastDraw();
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);
247   endFastDraw();
248 }
249
250 int SurfaceWin::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME
251 {
252   WaitForSingleObject(event,INFINITE); //since this might be called before surface
253   //allocation we will wait in this case, hopefully without deadlocks
254   if (!d3dsurface) {
255     return 0; //why does this happen
256   }
257   OsdWin* osd=((OsdWin*)(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!");
266     osd->EndPainting();
267     return 0;
268   }
269   osd->EndPainting();
270   return 0;
271 }
272
273 int SurfaceWin::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)
274 {
275   //I don't see code using this function, so I skip it, since it is a MVP specific interface
276   return 0;
277 }
278
279 void SurfaceWin::screenShot(const char* fileName)
280 {
281   //Isn't this for debugging only, so I won't implement it yet
282 }
283
284 void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
285 {
286   //Isn't this for debugging only, so I won't implement it yet
287 }
288 void SurfaceWin::ReleaseSurface()
289 {
290   ResetEvent(event);
291   LPDIRECT3DSURFACE9 temp_surf=d3dsurface;
292   LPDIRECT3DTEXTURE9 temp_text=d3dtexture;
293   d3dsurface=NULL;
294   d3dtexture=NULL;
295   sheight=swidth=0;
296   if (temp_surf) temp_surf->Release();
297   if (temp_text) temp_text->Release();
298 }
299
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
303   if (!d3dsurface) {
304     return ; //why does this happen
305   }
306   OsdWin* osd=((OsdWin*)(Osd::getInstance()));
307
308
309   D3DXIMAGE_INFO image_inf;
310   osd->BeginPainting();
311 //  D3DXGetImageInfoFromFile(fileName,&image_inf);
312   D3DXGetImageInfoFromResource(NULL,fileName,&image_inf);
313   RECT dest_rec={x,y,x+image_inf.Width,
314     y+image_inf.Height};
315 /*  if (D3DXLoadSurfaceFromFile(
316     d3dsurface,
317     NULL,
318     &dest_rec,
319     fileName,
320     NULL,
321     D3DX_FILTER_NONE,
322     0,
323     &image_inf)!=D3D_OK) {
324       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
325
326   }*/
327   if (D3DXLoadSurfaceFromResource(
328     d3dsurface,
329     NULL,
330     &dest_rec,
331     NULL,
332     fileName,
333     NULL,
334     D3DX_FILTER_NONE,
335     0,
336     &image_inf)!=D3D_OK) {
337       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
338
339   }
340   osd->EndPainting();
341   *width=image_inf.Width;
342   *height=image_inf.Height;
343
344 }
345
346 /*
347 void SurfaceWin::drawJpeg(char *buffer,ULONG buflength,DWORD x, DWORD y,DWORD *width, DWORD *height){
348   WaitForSingleObject(event,INFINITE); //since this might be called before surface
349   //allocation we will wait in this case, hopefully without deadlocks
350   if (!d3dsurface) {
351     return ; //why does this happen
352   }
353   OsdWin* osd=((OsdWin*)(Osd::getInstance()));
354
355
356   D3DXIMAGE_INFO image_inf;
357   osd->BeginPainting();
358 //  D3DXGetImageInfoFromFile(fileName,&image_inf);
359   D3DXGetImageInfoFromFileInMemory((void*)buffer,buflength,&image_inf);
360   RECT dest_rec={x,y,x+image_inf.Width,
361     y+image_inf.Height};
362 /*  if (D3DXLoadSurfaceFromFile(
363     d3dsurface,
364     NULL,
365     &dest_rec,
366     fileName,
367     NULL,
368     D3DX_FILTER_NONE,
369     0,
370     &image_inf)!=D3D_OK) {
371       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
372
373   }*/
374 /*  if (D3DXLoadSurfaceFromResource(
375     d3dsurface,
376     NULL,
377     &dest_rec,
378     NULL,
379     fileName,
380     NULL,
381     D3DX_FILTER_NONE,
382     0,
383     &image_inf)!=D3D_OK) {
384       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
385
386   }*
387   if (D3DXLoadSurfaceFromFileInMemory(
388     d3dsurface,
389     NULL,
390     &dest_rec,
391     (void*)buffer,
392     buflength,
393     NULL,
394     D3DX_FILTER_NONE,
395     0,
396     &image_inf)!=D3D_OK) {
397       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
398
399   }
400   osd->EndPainting();
401   *width=image_inf.Width;
402   *height=image_inf.Height;
403
404 }*/
405