]> git.vomp.tv Git - vompclient.git/blob - surfacewin.cc
Display channel name, duration, resume point and size on recording info screen
[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 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     OsdWinPixel* 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=((OsdWinPixel*)(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   OsdWinPixel* osd=((OsdWinPixel*)(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         OsdWinPixel* osd = ((OsdWinPixel*)(Osd::getInstance()));
307         osd->BeginPainting();
308
309         HDC dc;
310         HRESULT hres = d3dsurface->GetDC(&dc);
311         if (hres != D3D_OK) return; 
312
313         HRSRC hrc = FindResource(GetModuleHandle(NULL), fileName, RT_RCDATA);
314         DWORD size = SizeofResource(GetModuleHandle(NULL), hrc);
315         void *pointer = LockResource(LoadResource(GetModuleHandle(NULL),hrc));
316         HGLOBAL memhandle=GlobalAlloc(GMEM_MOVEABLE, size);
317         if (!memhandle)
318         {
319                 d3dsurface->ReleaseDC(dc);
320                 UnlockResource(hrc);
321                 return;
322         }
323         void *mempointer = GlobalLock(memhandle);
324         if (!mempointer) {
325                 d3dsurface->ReleaseDC(dc);
326                 GlobalUnlock(mempointer);
327                 GlobalFree(memhandle);
328                 UnlockResource(hrc);
329                 return;
330         }
331         
332         memcpy(mempointer, pointer, size);
333         UnlockResource(hrc);
334
335
336         IStream *memstream = NULL;
337         if (CreateStreamOnHGlobal(memhandle, FALSE, &memstream) != S_OK)
338         {
339                 GlobalUnlock(mempointer);
340                 GlobalFree(memhandle);
341                 d3dsurface->ReleaseDC(dc);
342                 
343                 return;
344         } 
345
346
347         Gdiplus::Graphics graphics(dc);
348         Gdiplus::Image image(memstream);
349         
350         *width = image.GetWidth();
351         *height = image.GetHeight();
352
353         graphics.DrawImage(&image, x, y, *width, *height);
354
355         memstream->Release();
356         GlobalUnlock(mempointer);
357         GlobalFree(memhandle);
358         
359         d3dsurface->ReleaseDC(dc);
360         osd->EndPainting();
361
362
363 }
364
365
366