]> git.vomp.tv Git - vompclient.git/blob - surfaceopengl.cc
dvbsubtitles fixup part 2
[vompclient.git] / surfaceopengl.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 <stdlib.h>
22
23 #include "surfaceopengl.h"
24 #include "osdopengl.h"
25 #include "bitmap.h"
26 #include "log.h"
27 #include "mutex.h"
28
29 inline unsigned int InternalColour(unsigned int c){
30         return (c &0x000000FF)<<16 |
31                                           (c &0x0000FF00) |
32                                           (c &0x00FF0000)>>16 |
33                                           (c &0xFF000000);
34 }
35
36 SurfaceOpenGL::SurfaceOpenGL(int id)
37 : Surface(id)
38 {
39         gltexture=0;
40   data=NULL;
41   sheight=swidth=0;
42 //  fastdraw=false;
43   srf_mutex.Lock();
44 }
45
46 SurfaceOpenGL::~SurfaceOpenGL()
47 {
48         srf_mutex.Lock();
49         if (data) {
50                 free(data);
51                 data=NULL;
52         } else {
53                 glDeleteTextures(1,&gltexture);
54         }
55         srf_mutex.Unlock();
56 }
57
58 int SurfaceOpenGL::create(UINT width, UINT height)
59 {
60         OsdOpenGL* osd=((OsdOpenGL*)(Osd::getInstance()));
61         //osd->BeginPainting();
62
63
64         if (this == screen) { // We do not need locking here, since the osd calls this
65
66                 swidth=width;
67                 sheight=height;
68                 glGenTextures(1, &gltexture);
69
70                 glBindTexture(GL_TEXTURE_2D, gltexture);
71
72                 void *image = malloc(sheight * swidth * 4);
73                 memset(image, 0, sheight * swidth * 4);
74         /*      for (int i=0;i< sheight * swidth * 4; i++) { //fill it with garbage, useful for debugging
75                         ((char*)image)[i]=i%255;
76                 }*/
77                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, swidth, sheight, 0, GL_RGBA,
78                                 GL_UNSIGNED_BYTE, image);
79
80         } else {
81                 sheight = height;
82                 swidth = width;
83                 data=(char*)malloc(sizeof(uint32_t)*width*height);
84         }
85
86
87         //osd->EndPainting();
88         srf_mutex.Unlock();
89         return 1;
90 }
91
92 void SurfaceOpenGL::display()
93 {
94 }
95
96 int SurfaceOpenGL::fillblt(int x, int y, int width, int height, const DrawStyle& c) {
97         srf_mutex.Lock();
98         //since this might be called before surface
99         //allocation we will wait in this case, hopefully without deadlocks
100         if (screen == this || !data ) {
101                 //This should not happen!
102                 srf_mutex.Unlock();
103                 return 0;
104
105         }
106         /*   OsdWin* osd=((OsdWin*)(Osd::getInstance()));
107
108          osd->BeginPainting();
109
110          glViewport(0,0,swidth,sheight);*/
111
112         //osd->EndPainting();
113         srf_mutex.Unlock();
114
115         unsigned int my_c=InternalColour(c.rgba());
116
117         int iheight=height;
118         if (height+y>sheight) iheight=sheight-y;
119         int iwidth=width;
120     if (width+x>swidth) iwidth=swidth-y;
121
122         unsigned int line;
123         unsigned int column;
124         for (line = y; line < (iheight + y); line++) {
125                 uint32_t *row = ((unsigned int*) (((char*) data) + (swidth * line + x)
126                                 * sizeof(uint32_t)));
127                 for (column = 0; column < iwidth; column++) {
128                         row[column] = my_c;
129                 }
130         }
131
132 /*      if (d3dsurface->UnlockRect() != D3D_OK) {
133                 osd->EndPainting();
134                 return 0;
135         }
136         osd->EndPainting();*/
137
138         return 0;
139 }
140
141
142 void SurfaceOpenGL::startFastDraw(){
143         srf_mutex.Lock();
144
145 }
146 void SurfaceOpenGL::endFastDraw(){
147         srf_mutex.Unlock();
148  }
149
150 void SurfaceOpenGL::drawPixel(int x, int y, Colour & colour, bool fastdraw) {
151   int c = (  (0xFF000000         )
152              | (colour.red    << 16)
153              | (colour.green  <<  8)
154              | (colour.blue        ) );
155
156     drawPixel(x, y, c, fastdraw);
157   }
158
159 void SurfaceOpenGL::drawPixel(int x, int y, unsigned int c, bool fastdraw) {
160         //FixMe: locking for every single Pixel will be painfully slow
161         if (screen == this) {
162                 //This should not happen!
163                 return ;
164         }
165         if (!data) {
166                 return; //why does this happen
167         }
168         //OsdWin* osd;
169         if (!fastdraw) {
170                 srf_mutex.Lock(); //since this might be called before surface
171         }
172         //allocation we will wait in this case, hopefully without deadlocks
173
174         //osd = ((OsdWin*) (Osd::getInstance()));
175
176         if (x >= swidth || y >= sheight)
177                 return; //do not draw outside the surface
178
179         unsigned int my_c=InternalColour(c);
180
181         unsigned int*row = (unsigned int*) (((char*) data + (swidth * y + x)
182                         * sizeof(uint32_t)));
183         row[0] = my_c;
184
185         if (!fastdraw) {
186                 srf_mutex.Unlock(); //since this might be called before surface
187         }
188
189 }
190
191 void SurfaceOpenGL::drawHorzLine(int x1, int x2, int y, const DrawStyle& c)
192 {
193    fillblt(x1, y, x2-x1, 1, c);
194 }
195
196 void SurfaceOpenGL::drawVertLine(int x, int y1, int y2, const DrawStyle& c)
197 {
198   fillblt(x, y1, 1, y2-y1, c);
199 }
200
201 void SurfaceOpenGL::drawBitmap(int x, int y, const Bitmap& bm,const DisplayRegion & region) //region should not matter for SD
202 {
203   // Temporary code? Draw one pixel at a time using drawPixel()
204   startFastDraw();
205   for (UINT j = 0; j < bm.getHeight(); ++j)
206     for (UINT i = 0; i < bm.getWidth(); ++i)
207       drawPixel(x+i, y+j, bm.getColour(i,j),true);
208   endFastDraw();
209 }
210
211 int SurfaceOpenGL::updateToScreen(int sx, int sy, int w, int h, int dx, int dy) // FIXME new, replace others with this FIXME
212 {
213 //      Log::getInstance()->log("Surface", Log::WARN, "UTS Mark1");
214         srf_mutex.Lock();//since this might be called before surface
215   //allocation we will wait in this case, hopefully without deadlocks
216
217   OsdOpenGL* osd=((OsdOpenGL*)(Osd::getInstance()));
218  // Log::getInstance()->log("Surface", Log::WARN, "UTS Mark2");
219   GLuint screengltexture=((SurfaceOpenGL*)screen)->getTexture();
220
221   osd->BeginPainting();
222  // Log::getInstance()->log("Surface", Log::WARN, "UTS Mark3");
223   glBindTexture(GL_TEXTURE_2D, screengltexture);
224 //  Log::getInstance()->log("Surface", Log::WARN, "UTS Mark4 %d",glGetError());
225
226   for (int y=0;y<h;y++) { //hopefully this is not too slow
227          // Log::getInstance()->log("Surface", Log::WARN, "UTS Mark4a %d %d %d %d %d %d",sx,sy,w,h,dx,dy);
228           glTexSubImage2D(GL_TEXTURE_2D,0,dx,(dy+y),w,1,GL_RGBA,GL_UNSIGNED_BYTE,
229                           data+((y+sy)*swidth+sx)*sizeof(uint32_t));
230
231
232   }
233
234   osd->EndPainting();
235
236   srf_mutex.Unlock();
237
238   return 0;
239 }
240
241 int SurfaceOpenGL::blt(int fd, unsigned long shandle, int sx, int sy, int width, int height, unsigned long dhandle, int dx, int dy)
242 {
243   //I don't see code using this function, so I skip it, since it is a MVP specific interface
244   return 0;
245 }
246
247 void SurfaceOpenGL::screenShot(const char* fileName)
248 {
249   //Isn't this for debugging only, so I won't implement it yet
250 }
251
252 void SurfaceOpenGL::readPixel(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b)
253 {
254   //Isn't this for debugging only, so I won't implement it yet
255 }
256
257
258 void SurfaceOpenGL::drawJpeg(const char *fileName,int x, int y,int *width, int *height){
259 }/*
260   WaitForSingleObject(event,INFINITE); //since this might be called before surface
261   //allocation we will wait in this case, hopefully without deadlocks
262   if (!d3dsurface) {
263     return ; //why does this happen
264   }
265   OsdWin* osd=((OsdWin*)(Osd::getInstance()));
266
267
268   D3DXIMAGE_INFO image_inf;
269   osd->BeginPainting();
270 //  D3DXGetImageInfoFromFile(fileName,&image_inf);
271   D3DXGetImageInfoFromResource(NULL,fileName,&image_inf);
272   RECT dest_rec={x,y,x+image_inf.Width,
273     y+image_inf.Height};
274 /*  if (D3DXLoadSurfaceFromFile(
275     d3dsurface,
276     NULL,
277     &dest_rec,
278     fileName,
279     NULL,
280     D3DX_FILTER_NONE,
281     0,
282     &image_inf)!=D3D_OK) {
283       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
284
285   }*
286   if (D3DXLoadSurfaceFromResource(
287     d3dsurface,
288     NULL,
289     &dest_rec,
290     NULL,
291     fileName,
292     NULL,
293     D3DX_FILTER_NONE,
294     0,
295     &image_inf)!=D3D_OK) {
296       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
297
298   }
299   osd->EndPainting();
300   *width=image_inf.Width;
301   *height=image_inf.Height;
302
303 }*/
304
305 /*
306 void SurfaceOpenGL::drawJpeg(char *buffer,ULONG buflength,DWORD x, DWORD y,DWORD *width, DWORD *height){
307   WaitForSingleObject(event,INFINITE); //since this might be called before surface
308   //allocation we will wait in this case, hopefully without deadlocks
309   if (!d3dsurface) {
310     return ; //why does this happen
311   }
312   OsdWin* osd=((OsdWin*)(Osd::getInstance()));
313
314
315   D3DXIMAGE_INFO image_inf;
316   osd->BeginPainting();
317 //  D3DXGetImageInfoFromFile(fileName,&image_inf);
318   D3DXGetImageInfoFromFileInMemory((void*)buffer,buflength,&image_inf);
319   RECT dest_rec={x,y,x+image_inf.Width,
320     y+image_inf.Height};
321 /*  if (D3DXLoadSurfaceFromFile(
322     d3dsurface,
323     NULL,
324     &dest_rec,
325     fileName,
326     NULL,
327     D3DX_FILTER_NONE,
328     0,
329     &image_inf)!=D3D_OK) {
330       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
331
332   }*/
333 /*  if (D3DXLoadSurfaceFromResource(
334     d3dsurface,
335     NULL,
336     &dest_rec,
337     NULL,
338     fileName,
339     NULL,
340     D3DX_FILTER_NONE,
341     0,
342     &image_inf)!=D3D_OK) {
343       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
344
345   }*
346   if (D3DXLoadSurfaceFromFileInMemory(
347     d3dsurface,
348     NULL,
349     &dest_rec,
350     (void*)buffer,
351     buflength,
352     NULL,
353     D3DX_FILTER_NONE,
354     0,
355     &image_inf)!=D3D_OK) {
356       Log::getInstance()->log("Surface", Log::DEBUG, "Could not open jpeg!");
357
358   }
359   osd->EndPainting();
360   *width=image_inf.Width;
361   *height=image_inf.Height;
362
363 }*/
364