]> git.vomp.tv Git - vompclient.git/blob - surfacewin.cc
Fix text corruption on channel list when returning from live TV
[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 void SurfaceWin::screenShot(const char* fileName)
285 {
286   //Isn't this for debugging only, so I won't implement it yet
287 }
288
289 void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
290 {
291   //Isn't this for debugging only, so I won't implement it yet
292 }
293 void SurfaceWin::ReleaseSurface()
294 {
295   ResetEvent(event);
296   LPDIRECT3DSURFACE9 temp_surf=d3dsurface;
297   LPDIRECT3DTEXTURE9 temp_text=d3dtexture;
298   d3dsurface=NULL;
299   d3dtexture=NULL;
300   sheight=swidth=0;
301   if (temp_surf) temp_surf->Release();
302   if (temp_text) temp_text->Release();
303 }
304
305 void SurfaceWin::drawJpeg(const char *fileName, int x, int y, int *width, int *height){
306         WaitForSingleObject(event, INFINITE); //since this might be called before surface
307         //allocation we will wait in this case, hopefully without deadlocks
308         if (!d3dsurface) {
309                 return; //why does this happen
310         }
311         OsdWinPixel* osd = ((OsdWinPixel*)(Osd::getInstance()));
312         osd->BeginPainting();
313
314         HDC dc;
315         HRESULT hres = d3dsurface->GetDC(&dc);
316         if (hres != D3D_OK) return; 
317
318         HRSRC hrc = FindResource(GetModuleHandle(NULL), fileName, RT_RCDATA);
319         DWORD size = SizeofResource(GetModuleHandle(NULL), hrc);
320         void *pointer = LockResource(LoadResource(GetModuleHandle(NULL),hrc));
321         HGLOBAL memhandle=GlobalAlloc(GMEM_MOVEABLE, size);
322         if (!memhandle)
323         {
324                 d3dsurface->ReleaseDC(dc);
325                 UnlockResource(hrc);
326                 return;
327         }
328         void *mempointer = GlobalLock(memhandle);
329         if (!mempointer) {
330                 d3dsurface->ReleaseDC(dc);
331                 GlobalUnlock(mempointer);
332                 GlobalFree(memhandle);
333                 UnlockResource(hrc);
334                 return;
335         }
336         
337         memcpy(mempointer, pointer, size);
338         UnlockResource(hrc);
339
340
341         IStream *memstream = NULL;
342         if (CreateStreamOnHGlobal(memhandle, FALSE, &memstream) != S_OK)
343         {
344                 GlobalUnlock(mempointer);
345                 GlobalFree(memhandle);
346                 d3dsurface->ReleaseDC(dc);
347                 
348                 return;
349         } 
350
351
352         Gdiplus::Graphics graphics(dc);
353         Gdiplus::Image image(memstream);
354         
355         *width = image.GetWidth();
356         *height = image.GetHeight();
357
358         graphics.DrawImage(&image, x, y, *width, *height);
359
360         memstream->Release();
361         GlobalUnlock(mempointer);
362         GlobalFree(memhandle);
363         
364         d3dsurface->ReleaseDC(dc);
365         osd->EndPainting();
366
367
368 }
369
370
371