1/*
2 * Copyright © 2014 Jon Turney
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include "windowsgl.h"
25#include "windowsgl_internal.h"
26#include "windowsdriconst.h"
27#include "wgl.h"
28
29#include <stdio.h>
30
31/*
32 * Window drawable
33 */
34
35static
36HDC window_getdc(windowsDrawable *d)
37{
38   return GetDC(d->hWnd);
39}
40
41static
42void window_releasedc(windowsDrawable *d, HDC dc)
43{
44   ReleaseDC(d->hWnd, dc);
45}
46
47static struct windowsdrawable_callbacks window_callbacks = {
48   .type = WindowsDRIDrawableWindow,
49   .getdc = window_getdc,
50   .releasedc = window_releasedc
51};
52
53/*
54 * Pixmap drawable
55 */
56
57static
58HDC pixmap_getdc(windowsDrawable *d)
59{
60   return d->dibDC;
61}
62
63static
64void pixmap_releasedc(windowsDrawable *d, HDC dc)
65{
66   GdiFlush();
67}
68
69static struct windowsdrawable_callbacks pixmap_callbacks = {
70   .type = WindowsDRIDrawablePixmap,
71   .getdc = pixmap_getdc,
72   .releasedc = pixmap_releasedc
73};
74
75/*
76 * Pbuffer drawable
77 */
78
79static
80HDC pbuffer_getdc(windowsDrawable *d)
81{
82   return wglGetPbufferDCARB(d->hPbuffer);
83}
84
85static
86void pbuffer_releasedc(windowsDrawable *d, HDC dc)
87{
88   wglReleasePbufferDCARB(d->hPbuffer, dc);
89}
90
91static struct windowsdrawable_callbacks pbuffer_callbacks = {
92   .type = WindowsDRIDrawablePbuffer,
93   .getdc = pbuffer_getdc,
94   .releasedc = pbuffer_releasedc
95};
96
97/*
98 *
99 */
100
101windowsDrawable *
102windows_create_drawable(int type, void *handle)
103{
104   windowsDrawable *d;
105
106   d = calloc(1, sizeof *d);
107   if (d == NULL)
108      return NULL;
109
110   switch (type)
111   {
112   case WindowsDRIDrawableWindow:
113      d->hWnd = handle;
114      d->callbacks = &window_callbacks;
115      break;
116
117   case WindowsDRIDrawablePixmap:
118   {
119      BITMAPINFOHEADER *pBmpHeader;
120      void *pBits;
121
122      char name[MAX_PATH];
123
124      d->callbacks = &pixmap_callbacks;
125
126      // Access file mapping object by a name
127      snprintf(name, sizeof(name), "Local\\CYGWINX_WINDOWSDRI_%08x", (unsigned int)(uintptr_t)handle);
128      d->hSection = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
129      if (!d->hSection)
130         printf("OpenFileMapping failed %x\n", (int)GetLastError());
131
132      // Create a screen-compatible DC
133      d->dibDC = CreateCompatibleDC(NULL);
134
135      // Map the shared memory section to access the BITMAPINFOHEADER
136      pBmpHeader = (BITMAPINFOHEADER *)MapViewOfFile(d->hSection, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(BITMAPINFOHEADER));
137      if (!pBmpHeader)
138         printf("MapViewOfFile failed %x\n", (int)GetLastError());
139
140      // Create a DIB using the file mapping
141      d->hDIB = CreateDIBSection(d->dibDC, (BITMAPINFO *) pBmpHeader,
142                                 DIB_RGB_COLORS, &pBits, d->hSection,
143                                 sizeof(BITMAPINFOHEADER));
144
145      // Done with the BITMAPINFOHEADER
146      UnmapViewOfFile(pBmpHeader);
147
148      // Select the DIB into the DC
149      d->hOldDIB = SelectObject(d->dibDC, d->hDIB);
150   }
151   break;
152
153   case WindowsDRIDrawablePbuffer:
154      d->hPbuffer = handle;
155      d->callbacks = &pbuffer_callbacks;
156      break;
157   }
158
159   return d;
160}
161
162void
163windows_destroy_drawable(windowsDrawable *drawable)
164{
165   switch (drawable->callbacks->type)
166   {
167   case WindowsDRIDrawableWindow:
168      break;
169
170   case WindowsDRIDrawablePixmap:
171   {
172      // Select the default DIB into the DC
173      SelectObject(drawable->dibDC, drawable->hOldDIB);
174
175      // delete the screen-compatible DC
176      DeleteDC(drawable->dibDC);
177
178      // Delete the DIB
179      DeleteObject(drawable->hDIB);
180
181      // Close the file mapping object
182      CloseHandle(drawable->hSection);
183   }
184   break;
185
186   case WindowsDRIDrawablePbuffer:
187
188      break;
189   }
190
191   free(drawable);
192}
193