]> git.vomp.tv Git - vompclient.git/blob - surfacewin.cc
DVB Subtitles: changes for Windows port
[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   startFastDraw();
223   for (UINT j = 0; j < bm.getHeight(); ++j)
224     for (UINT i = 0; i < bm.getWidth(); ++i)
225       drawPixel(x+i, y+j, bm.getColour(i,j));
226   endFastDraw();
227 }
228
229 int SurfaceWin::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME
230 {
231   WaitForSingleObject(event,INFINITE); //since this might be called before surface
232   //allocation we will wait in this case, hopefully without deadlocks
233   if (!d3dsurface) {
234     return 0; //why does this happen
235   }
236   OsdWin* osd=((OsdWin*)(Osd::getInstance()));
237   LPDIRECT3DDEVICE9 d3ddev=osd->getD3dDev();
238     LPDIRECT3DSURFACE9 screensurface=((SurfaceWin*)screen)->getD3dsurface();
239   if (!screensurface) return 0;
240   RECT sourcerect={sx,sy,sx+w,sy+h};
241   POINT destpoint={dx,dy};
242   osd->BeginPainting();
243   if (d3ddev->UpdateSurface(d3dsurface,&sourcerect,screensurface,&destpoint)!=D3D_OK) {
244     Log::getInstance()->log("Surface", Log::DEBUG, "Could not update to Screen!");
245     osd->EndPainting();
246     return 0;
247   }
248   osd->EndPainting();
249   return 0;
250 }
251
252 int SurfaceWin::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)
253 {
254   //I don't see code using this function, so I skip it, since it is a MVP specific interface
255   return 0;
256 }
257
258 void SurfaceWin::screenShot(char* fileName)
259 {
260   //Isn't this for debugging only, so I won't implement it yet
261 }
262
263 void SurfaceWin::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
264 {
265   //Isn't this for debugging only, so I won't implement it yet
266 }
267 void SurfaceWin::ReleaseSurface()
268 {
269   ResetEvent(event);
270   LPDIRECT3DSURFACE9 temp_surf=d3dsurface;
271   LPDIRECT3DTEXTURE9 temp_text=d3dtexture;
272   d3dsurface=NULL;
273   d3dtexture=NULL;
274   sheight=swidth=0;
275   if (temp_surf) temp_surf->Release();
276   if (temp_text) temp_text->Release();
277 }
278 /*
279 void SurfaceWin::drawJpeg(char *fileName,DWORD x, DWORD y,DWORD *width, DWORD *height){
280   WaitForSingleObject(event,INFINITE); //since this might be called before surface
281   //allocation we will wait in this case, hopefully without deadlocks
282   if (!d3dsurface) {
283     return ; //why does this happen
284   }
285   OsdWin* osd=((OsdWin*)(Osd::getInstance()));
286
287
288   D3DXIMAGE_INFO image_inf;
289   osd->BeginPainting();
290 //  D3DXGetImageInfoFromFile(fileName,&image_inf);
291   D3DXGetImageInfoFromResource(NULL,fileName,&image_inf);
292   RECT dest_rec={x,y,x+image_inf.Width,
293     y+image_inf.Height};
294 /*  if (D3DXLoadSurfaceFromFile(
295     d3dsurface,
296     NULL,
297     &dest_rec,
298     fileName,
299     NULL,
300     D3DX_FILTER_NONE,
301     0,
302     &image_inf)!=D3D_OK) {
303       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
304
305   }*
306   if (D3DXLoadSurfaceFromResource(
307     d3dsurface,
308     NULL,
309     &dest_rec,
310     NULL,
311     fileName,
312     NULL,
313     D3DX_FILTER_NONE,
314     0,
315     &image_inf)!=D3D_OK) {
316       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
317
318   }
319   osd->EndPainting();
320   *width=image_inf.Width;
321   *height=image_inf.Height;
322
323 }
324
325 void SurfaceWin::drawJpeg(char *buffer,ULONG buflength,DWORD x, DWORD y,DWORD *width, DWORD *height){
326   WaitForSingleObject(event,INFINITE); //since this might be called before surface
327   //allocation we will wait in this case, hopefully without deadlocks
328   if (!d3dsurface) {
329     return ; //why does this happen
330   }
331   OsdWin* osd=((OsdWin*)(Osd::getInstance()));
332
333
334   D3DXIMAGE_INFO image_inf;
335   osd->BeginPainting();
336 //  D3DXGetImageInfoFromFile(fileName,&image_inf);
337   D3DXGetImageInfoFromFileInMemory((void*)buffer,buflength,&image_inf);
338   RECT dest_rec={x,y,x+image_inf.Width,
339     y+image_inf.Height};
340 /*  if (D3DXLoadSurfaceFromFile(
341     d3dsurface,
342     NULL,
343     &dest_rec,
344     fileName,
345     NULL,
346     D3DX_FILTER_NONE,
347     0,
348     &image_inf)!=D3D_OK) {
349       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
350
351   }*/
352 /*  if (D3DXLoadSurfaceFromResource(
353     d3dsurface,
354     NULL,
355     &dest_rec,
356     NULL,
357     fileName,
358     NULL,
359     D3DX_FILTER_NONE,
360     0,
361     &image_inf)!=D3D_OK) {
362       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
363
364   }*
365   if (D3DXLoadSurfaceFromFileInMemory(
366     d3dsurface,
367     NULL,
368     &dest_rec,
369     (void*)buffer,
370     buflength,
371     NULL,
372     D3DX_FILTER_NONE,
373     0,
374     &image_inf)!=D3D_OK) {
375       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
376
377   }
378   osd->EndPainting();
379   *width=image_inf.Width;
380   *height=image_inf.Height;
381
382 }*/
383