summaryrefslogtreecommitdiff
path: root/legacy/evas/src/modules/engines/software_16_wince/evas_wince_gapi_buffer.c
blob: ecb47952bad0638e591823012d2a013ee15343a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
#include "evas_common.h"
#include "evas_engine.h"


typedef int (*evas_engine_wince_close_display)();

typedef struct Evas_Engine_WinCE_GAPI_Priv Evas_Engine_WinCE_GAPI_Priv;


#define GETGXINFO 0x00020000

typedef struct
{
    long Version;               //00 (should filled with 100 before calling ExtEscape)
    void *pvFrameBuffer;        //04
    unsigned long cbStride;     //08
    unsigned long cxWidth;      //0c
    unsigned long cyHeight;     //10
    unsigned long cBPP;         //14
    unsigned long ffFormat;     //18
    char Unused[0x84 - 7 * 4];
} _GXDeviceInfo;


#define LINK(type,name,import) \
  name = (gapi_##type)GetProcAddress (gapi_lib, import)

#define GX_FULLSCREEN 0x01
#define GX_NORMALKEYS 0x02

#define kfDirect555   0x40
#define kfDirect565   0x80


typedef struct
{
   DWORD cxWidth;
   DWORD cyHeight;
   LONG  cbxPitch;
   LONG  cbyPitch;
   LONG  cBPP;
   DWORD ffFormat;
} _GAPI_Display_Properties;

typedef int                      (*gapi_display_open)(HWND hWnd, DWORD dwFlags);
typedef int                      (*gapi_display_close)();
typedef _GAPI_Display_Properties (*gapi_display_properties_get)(void);
typedef void*                    (*gapi_draw_begin)(void);
typedef int                      (*gapi_draw_end)(void);
typedef int                      (*gapi_suspend)(void);
typedef int                      (*gapi_resume)(void);

gapi_suspend          suspend = NULL;
gapi_resume           resume = NULL;

int
evas_software_wince_gapi_suspend(void)
{
   if (suspend)
     return suspend();
   else
     return 0;
}

int
evas_software_wince_gapi_resume(void)
{
   if (resume)
     return resume();
   else
     return 0;
}


struct Evas_Engine_WinCE_GAPI_Priv
{
   HMODULE            lib;
   gapi_display_close close_display;
   gapi_draw_begin    draw_begin;
   gapi_draw_end      draw_end;
   void              *buffer;
   int                width;
   int                height;
   int                stride;
};

void *
evas_software_wince_gapi_init(HWND window,
                              int  width,
                              int  height)
{
   WCHAR                        oemstr[100];
   _GAPI_Display_Properties     prop;
   HMODULE                      gapi_lib;
   Evas_Engine_WinCE_GAPI_Priv *priv;

   gapi_display_open            display_open = NULL;
   gapi_display_close           display_close = NULL;
   gapi_display_properties_get  display_properties_get = NULL;
   gapi_draw_begin              draw_begin = NULL;
   gapi_draw_end                draw_end = NULL;

   priv = (Evas_Engine_WinCE_GAPI_Priv *)malloc(sizeof(Evas_Engine_WinCE_GAPI_Priv));
   if (!priv)
     return NULL;

   gapi_lib = LoadLibrary(L"\\Windows\\gx.dll");
   if (!gapi_lib)
     {
        gapi_lib = LoadLibrary(L"gx.dll");
        if (!gapi_lib)
          {
             ERROR("[Engine] [WinCE GAPI] Can not load gx.dll");
             goto free_priv;
          }
     }

   LINK(display_open, display_open, L"?GXOpenDisplay@@YAHPAUHWND__@@K@Z");
   LINK(display_close, display_close, L"?GXCloseDisplay@@YAHXZ");
   LINK(display_properties_get, display_properties_get, L"?GXGetDisplayProperties@@YA?AUGXDisplayProperties@@XZ");
   LINK(draw_begin, draw_begin, L"?GXBeginDraw@@YAPAXXZ");
   LINK(draw_end, draw_end, L"?GXEndDraw@@YAHXZ");
   LINK(suspend, suspend, L"?GXSuspend@@YAHXZ" );
   LINK(resume, resume, L"?GXResume@@YAHXZ" );

   if (!display_open ||
       !display_close ||
       !display_properties_get ||
       !draw_begin ||
       !draw_end ||
       !suspend ||
       !resume)
     {
       ERROR("[Engine] [WinCE GAPI] Can not find valid symbols");
        goto free_lib;
     }

   if (!display_open(window, GX_FULLSCREEN))
     {
        ERROR("[Engine] [WinCE GAPI] Can not open display");
        goto free_lib;
     }

   prop = display_properties_get();

   // verify pixel format
   if(!(prop.ffFormat & kfDirect565) || (prop.cBPP != 16))
     {
        ERROR("[Engine] [WinCE GAPI] display format mismatch");
        goto close_display;
     }

   // verify we have a vga device
   if ((GetSystemMetrics(SM_CXSCREEN) != (int)prop.cxWidth) ||
       (GetSystemMetrics(SM_CYSCREEN) != (int)prop.cyHeight))
     {
        ERROR("[Engine] [WinCE GAPI] display size mismatch");
        goto close_display;
     }

   priv->lib = gapi_lib;
   priv->close_display = display_close;
   priv->draw_begin = draw_begin;
   priv->draw_end = draw_end;

   /* GAPI on Ipaq H38** and H39** is completely buggy */
   /* They are detected as portrait device (width = 240 and height = 320) */
   /* but the framebuffer is managed like a landscape device : */
   /*
     240
 +---------+
 |         |
 |         |
 |         |
 |         |
 |         | 320
 | ^^^     |
 | |||     |
 | |||     |
 | |||     |
 +---------+
  ---->

   */
   /* So these devices are considered as landscape devices */
   /* and width and height are switched. */
   /* Other devices are managed normally : */
   /*
     240
  +---------+
| |--->     |
| |--->     |
| |--->     |
v |         |
  |         | 320
  |         |
  |         |
  |         |
  |         |
  +---------+

    */

   SystemParametersInfo (SPI_GETOEMINFO, sizeof (oemstr), oemstr, 0);

   if (((oemstr[12] == 'H') &&
        (oemstr[13] == '3') &&
        (oemstr[14] == '8')) ||
       ((oemstr[12] == 'H') &&
        (oemstr[13] == '3') &&
        (oemstr[14] == '9')))
     {
        _GXDeviceInfo gxInfo = { 0 };
        HDC           dc;
        int           result;

        priv->width = prop.cyHeight;
        priv->height = prop.cxWidth;
        priv->stride = prop.cbxPitch;

        dc = GetDC (window);
        if (!dc)
          {
             ERROR("[Engine] [WinCE GAPI] Can not get device");
             goto close_display;
          }

        gxInfo.Version = 100;
        result = ExtEscape(dc, GETGXINFO, 0, NULL, sizeof(gxInfo),
                           (char *) &gxInfo);
        if (result <= 0)
          {
             ERROR("[Engine] [WinCE GAPI] ExtEscape failed");
             ReleaseDC(window, dc);
             goto close_display;
          }

        priv->buffer = gxInfo.pvFrameBuffer;
        ReleaseDC(window, dc);
     }
   else
     {
        priv->width = prop.cxWidth;
        priv->height = prop.cyHeight;
        priv->stride = prop.cbyPitch;
        priv->buffer = NULL;
     }

   if ((priv->width != width) ||
       (priv->height != height))
     {
        WARN("[Engine] [WinCE GAPI] Size mismatch");
        WARN("[Engine] [WinCE GAPI] asked: %dx%d", width, height);
        WARN("[Engine] [WinCE GAPI] got  : %dx%d", priv->width, priv->height);
        goto close_display;
     }

   return priv;

 close_display:
   display_close();
 free_lib:
   FreeLibrary(gapi_lib);
 free_priv:
   free(priv);
   return NULL;
}

void
evas_software_wince_gapi_shutdown(void *priv)
{
   Evas_Engine_WinCE_GAPI_Priv *p;

   p = (Evas_Engine_WinCE_GAPI_Priv *)priv;
   p->close_display();
   suspend = NULL;
   resume = NULL;
   FreeLibrary(p->lib);
   free(p);
}


FB_Output_Buffer *
evas_software_wince_gapi_output_buffer_new(void *priv,
                                           int   width,
                                           int   height)
{
   FB_Output_Buffer *fbob;
   void             *buffer;

   fbob = calloc(1, sizeof(FB_Output_Buffer));
   if (!fbob) return NULL;

   buffer = malloc (width * height * 2); /* we are sure to have 16bpp */
   if (!buffer)
     {
        free(fbob);
        return NULL;
     }

   fbob->priv = priv;

   fbob->im = (Soft16_Image *) evas_cache_image_data(evas_common_soft16_image_cache_get(), width, height, (DATA32 *)buffer, 0, EVAS_COLORSPACE_RGB565_A5P);
   if (fbob->im)
     fbob->im->stride = ((Evas_Engine_WinCE_GAPI_Priv *)priv)->stride >> 1;

   return fbob;
}

void
evas_software_wince_gapi_output_buffer_free(FB_Output_Buffer *fbob)
{
   free(fbob->im->pixels);
   free(fbob);
}

void
evas_software_wince_gapi_output_buffer_paste(FB_Output_Buffer *fbob)
{
   Evas_Engine_WinCE_GAPI_Priv *priv;
   void                        *buffer;

   priv = (Evas_Engine_WinCE_GAPI_Priv *)fbob->priv;

   buffer = priv->draw_begin();
   if (!buffer)
     return;

   if (priv->buffer) buffer = priv->buffer;

   if ((fbob->im->cache_entry.w == priv->width) &&
       (fbob->im->cache_entry.h == priv->height))
     memcpy(buffer, fbob->im->pixels,
            priv->width * priv->height * 2);

   priv->draw_end();
}

void
evas_software_wince_gapi_surface_resize(FB_Output_Buffer *fbob)
{
}