Update change log.
[platform/upstream/cairo.git] / boilerplate / cairo-boilerplate-wgl.c
1 /* cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Chris Wilson
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it either under the terms of the GNU Lesser General Public
7  * License version 2.1 as published by the Free Software Foundation
8  * (the "LGPL") or, at your option, under the terms of the Mozilla
9  * Public License Version 1.1 (the "MPL"). If you do not alter this
10  * notice, a recipient may use your version of this file under either
11  * the MPL or the LGPL.
12  *
13  * You should have received a copy of the LGPL along with this library
14  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16  * You should have received a copy of the MPL along with this library
17  * in the file COPYING-MPL-1.1
18  *
19  * The contents of this file are subject to the Mozilla Public License
20  * Version 1.1 (the "License"); you may not use this file except in
21  * compliance with the License. You may obtain a copy of the License at
22  * http://www.mozilla.org/MPL/
23  *
24  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26  * the specific language governing rights and limitations.
27  *
28  * The Original Code is the cairo graphics library.
29  *
30  * The Initial Developer of the Original Code is Chris Wilson.
31  *
32  * Contributor(s):
33  *      Zoxc <zoxc32@gmail.com>
34  */
35
36 #include "cairo-boilerplate-private.h"
37
38 #include <cairo-gl.h>
39
40 static const cairo_user_data_key_t gl_closure_key;
41
42 typedef struct _wgl_target_closure {
43     HWND wnd;
44     HDC dc;
45     HGLRC rc;
46     cairo_device_t *device;
47     cairo_surface_t *surface;
48 } wgl_target_closure_t;
49
50 static void
51 _cairo_boilerplate_wgl_cleanup (void *closure)
52 {
53     wgl_target_closure_t *wgltc = closure;
54
55     cairo_device_finish (wgltc->device);
56     cairo_device_destroy (wgltc->device);
57
58     wglDeleteContext(wgltc->rc);
59
60     ReleaseDC(wgltc->wnd, wgltc->dc);
61     DestroyWindow (wgltc->wnd);
62
63     free (wgltc);
64 }
65
66 static void
67 _cairo_boilerplate_wgl_create_window (int                   width,
68                                       int                   height,
69                                       wgl_target_closure_t *wgltc)
70 {
71     WNDCLASSEXA wincl;
72     PIXELFORMATDESCRIPTOR pfd;
73     int format;
74     cairo_surface_t *surface;
75     
76     ZeroMemory (&wincl, sizeof (WNDCLASSEXA));
77     wincl.cbSize = sizeof (WNDCLASSEXA);
78     wincl.hInstance = GetModuleHandle (0);
79     wincl.lpszClassName = "cairo_boilerplate_wgl_dummy";
80     wincl.lpfnWndProc = DefWindowProcA;
81     wincl.style = CS_OWNDC;
82
83     RegisterClassExA (&wincl);
84     
85     wgltc->wnd = CreateWindow ("cairo_boilerplate_wgl_dummy", 0, WS_POPUP, 0, 0, width, height, 0, 0, 0, 0);
86     wgltc->dc = GetDC (wgltc->wnd);
87
88     ZeroMemory (&pfd, sizeof (PIXELFORMATDESCRIPTOR));
89     pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
90     pfd.nVersion = 1;
91     pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
92     pfd.iPixelType = PFD_TYPE_RGBA;
93     pfd.cColorBits = 24;
94     pfd.cDepthBits = 16;
95     pfd.iLayerType = PFD_MAIN_PLANE;
96
97     format = ChoosePixelFormat (wgltc->dc, &pfd);
98     SetPixelFormat (wgltc->dc, format, &pfd);
99     
100     wgltc->rc = wglCreateContext (wgltc->dc);
101     wgltc->device = cairo_wgl_device_create (wgltc->rc);
102 }
103
104 static cairo_surface_t *
105 _cairo_boilerplate_wgl_create_surface (const char                *name,
106                                        cairo_content_t            content,
107                                        double                     width,
108                                        double                     height,
109                                        double                     max_width,
110                                        double                     max_height,
111                                        cairo_boilerplate_mode_t   mode,
112                                        void                     **closure)
113 {
114     wgl_target_closure_t *wgltc;
115     cairo_surface_t *surface;
116     
117     wgltc = calloc (1, sizeof (wgl_target_closure_t));
118     
119     *closure = wgltc;
120
121     _cairo_boilerplate_wgl_create_window(0, 0, wgltc);
122     
123     if (width == 0)
124         width = 1;
125     if (height == 0)
126         height = 1;
127     
128     wgltc->surface = surface = cairo_gl_surface_create (wgltc->device,
129                                                        content,
130                                                        ceil (width),
131                                                        ceil (height));
132     if (cairo_surface_status (surface)) {
133         _cairo_boilerplate_wgl_cleanup (wgltc);
134         return NULL;
135     }
136
137     return surface;
138 }
139
140 static cairo_surface_t *
141 _cairo_boilerplate_wgl_for_create_window (const char                *name,
142                                           cairo_content_t            content,
143                                           double                     width,
144                                           double                     height,
145                                           double                     max_width,
146                                           double                     max_height,
147                                           cairo_boilerplate_mode_t   mode,
148                                           void                     **closure)
149 {
150     wgl_target_closure_t *wgltc;
151     cairo_surface_t *surface;
152     
153     wgltc = calloc (1, sizeof (wgl_target_closure_t));
154     
155     *closure = wgltc;
156
157      _cairo_boilerplate_wgl_create_window(width, height, wgltc);
158     
159     wgltc->surface = surface = cairo_gl_surface_create_for_dc (wgltc->device,
160                                                        wgltc->dc,
161                                                        ceil (width),
162                                                        ceil (height));
163     
164     if (cairo_surface_status (surface)) {
165         _cairo_boilerplate_wgl_cleanup (wgltc);
166         return NULL;
167     }
168
169     return surface;
170 }
171
172 static cairo_status_t
173 _cairo_boilerplate_wgl_finish_window (cairo_surface_t *surface)
174 {
175     wgl_target_closure_t *wgltc = cairo_surface_get_user_data (surface,
176                                                              &gl_closure_key);
177
178     if (wgltc != NULL && wgltc->surface != NULL) {
179         cairo_t *cr;
180
181         cr = cairo_create (wgltc->surface);
182         cairo_surface_set_device_offset (surface, 0, 0);
183         cairo_set_source_surface (cr, surface, 0, 0);
184         cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
185         cairo_paint (cr);
186         cairo_destroy (cr);
187
188         surface = wgltc->surface;
189     }
190
191     cairo_gl_surface_swapbuffers (surface);
192     return CAIRO_STATUS_SUCCESS;
193 }
194
195 static void
196 _cairo_boilerplate_wgl_synchronize (void *closure)
197 {
198     wgl_target_closure_t *wgltc = closure;
199
200     if (cairo_device_acquire (wgltc->device))
201         return;
202
203     glFinish ();
204
205     cairo_device_release (wgltc->device);
206 }
207
208 static const cairo_boilerplate_target_t targets[] = {
209     {
210         "gl", "gl", NULL, NULL,
211         CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
212         "cairo_gl_surface_create",
213         _cairo_boilerplate_wgl_create_surface,
214         cairo_surface_create_similar,
215         NULL, NULL,
216         _cairo_boilerplate_get_image_surface,
217         cairo_surface_write_to_png,
218         _cairo_boilerplate_wgl_cleanup,
219         _cairo_boilerplate_wgl_synchronize,
220         NULL,
221         TRUE, FALSE, FALSE
222     },
223     {
224         "gl-dc", "gl", NULL, NULL,
225         CAIRO_SURFACE_TYPE_GL, CAIRO_CONTENT_COLOR_ALPHA, 1,
226         "cairo_gl_surface_create_for_dc",
227         _cairo_boilerplate_wgl_for_create_window,
228         NULL,
229         _cairo_boilerplate_wgl_finish_window,
230         _cairo_boilerplate_get_image_surface,
231         cairo_surface_write_to_png,
232         _cairo_boilerplate_wgl_cleanup,
233         _cairo_boilerplate_wgl_synchronize,
234         NULL,
235         FALSE, FALSE, FALSE
236     },
237 };
238
239 CAIRO_BOILERPLATE (wgl, targets)