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