Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* cairo - a vector graphics library with display and print output
  2.  *
  3.  * Copyright © 2009 Eric Anholt
  4.  * Copyright © 2009 Chris Wilson
  5.  * Copyright © 2005 Red Hat, Inc
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it either under the terms of the GNU Lesser General Public
  9.  * License version 2.1 as published by the Free Software Foundation
  10.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  11.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  12.  * notice, a recipient may use your version of this file under either
  13.  * the MPL or the LGPL.
  14.  *
  15.  * You should have received a copy of the LGPL along with this library
  16.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  17.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  18.  * You should have received a copy of the MPL along with this library
  19.  * in the file COPYING-MPL-1.1
  20.  *
  21.  * The contents of this file are subject to the Mozilla Public License
  22.  * Version 1.1 (the "License"); you may not use this file except in
  23.  * compliance with the License. You may obtain a copy of the License at
  24.  * http://www.mozilla.org/MPL/
  25.  *
  26.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  27.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  28.  * the specific language governing rights and limitations.
  29.  *
  30.  * The Original Code is the cairo graphics library.
  31.  *
  32.  * The Initial Developer of the Original Code is Red Hat, Inc.
  33.  *
  34.  * Contributor(s):
  35.  *      Carl Worth <cworth@cworth.org>
  36.  *      Chris Wilson <chris@chris-wilson.co.uk>
  37.  *      Zoxc <zoxc32@gmail.com>
  38.  */
  39.  
  40. #include "cairoint.h"
  41.  
  42. #include "cairo-gl-private.h"
  43.  
  44. #include "cairo-error-private.h"
  45.  
  46. #define WIN32_LEAN_AND_MEAN
  47. #include <windows.h>
  48.  
  49. typedef struct _cairo_wgl_context {
  50.     cairo_gl_context_t base;
  51.  
  52.     HDC dummy_dc;
  53.     HWND dummy_wnd;
  54.     HGLRC rc;
  55.  
  56.     HDC prev_dc;
  57.     HGLRC prev_rc;
  58. } cairo_wgl_context_t;
  59.  
  60. typedef struct _cairo_wgl_surface {
  61.     cairo_gl_surface_t base;
  62.  
  63.     HDC dc;
  64. } cairo_wgl_surface_t;
  65.  
  66. static void
  67. _wgl_acquire (void *abstract_ctx)
  68. {
  69.     cairo_wgl_context_t *ctx = abstract_ctx;
  70.  
  71.     HDC current_dc;
  72.  
  73.     ctx->prev_dc = wglGetCurrentDC ();
  74.     ctx->prev_rc = wglGetCurrentContext ();
  75.  
  76.     if (ctx->base.current_target == NULL ||
  77.         _cairo_gl_surface_is_texture (ctx->base.current_target))
  78.     {
  79.         current_dc = ctx->dummy_dc;
  80.     }
  81.     else
  82.     {
  83.         cairo_wgl_surface_t *surface = (cairo_wgl_surface_t *) ctx->base.current_target;
  84.         current_dc = surface->dc;
  85.     }
  86.  
  87.     if (ctx->prev_dc != current_dc ||
  88.         (ctx->prev_rc != ctx->rc &&
  89.          current_dc != ctx->dummy_dc))
  90.     {
  91.         wglMakeCurrent (current_dc, ctx->rc);
  92.     }
  93. }
  94.  
  95. static void
  96. _wgl_make_current (void *abstract_ctx, cairo_gl_surface_t *abstract_surface)
  97. {
  98.     cairo_wgl_context_t *ctx = abstract_ctx;
  99.     cairo_wgl_surface_t *surface = (cairo_wgl_surface_t *) abstract_surface;
  100.  
  101.     /* Set the window as the target of our context. */
  102.     wglMakeCurrent (surface->dc, ctx->rc);
  103. }
  104.  
  105. static void
  106. _wgl_release (void *abstract_ctx)
  107. {
  108.     cairo_wgl_context_t *ctx = abstract_ctx;
  109.  
  110.     if (ctx->prev_dc != wglGetCurrentDC () ||
  111.         ctx->prev_rc != wglGetCurrentContext ())
  112.     {
  113.         wglMakeCurrent (ctx->prev_dc,
  114.                         ctx->prev_rc);
  115.     }
  116. }
  117.  
  118. static void
  119. _wgl_swap_buffers (void *abstract_ctx,
  120.                    cairo_gl_surface_t *abstract_surface)
  121. {
  122.     cairo_wgl_surface_t *surface = (cairo_wgl_surface_t *) abstract_surface;
  123.  
  124.     SwapBuffers (surface->dc);
  125. }
  126.  
  127. static void
  128. _wgl_destroy (void *abstract_ctx)
  129. {
  130.     cairo_wgl_context_t *ctx = abstract_ctx;
  131.  
  132.     if (ctx->dummy_dc != 0) {  
  133.         wglMakeCurrent (ctx->dummy_dc, 0);
  134.         ReleaseDC (ctx->dummy_wnd, ctx->dummy_dc);
  135.         DestroyWindow (ctx->dummy_wnd);
  136.     }
  137. }
  138.  
  139. static cairo_status_t
  140. _wgl_dummy_ctx (cairo_wgl_context_t *ctx)
  141. {
  142.     WNDCLASSEXA wincl;
  143.     PIXELFORMATDESCRIPTOR pfd;
  144.     int format;
  145.     HDC dc;
  146.  
  147.     ZeroMemory (&wincl, sizeof (WNDCLASSEXA));
  148.     wincl.cbSize = sizeof (WNDCLASSEXA);
  149.     wincl.hInstance = GetModuleHandle (0);
  150.     wincl.lpszClassName = "cairo_wgl_context_dummy";
  151.     wincl.lpfnWndProc = DefWindowProcA;
  152.     wincl.style = CS_OWNDC;
  153.  
  154.     RegisterClassExA (&wincl);
  155.  
  156.     ctx->dummy_wnd = CreateWindowA ("cairo_wgl_context_dummy", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
  157.     ctx->dummy_dc = GetDC (ctx->dummy_wnd);
  158.  
  159.     ZeroMemory (&pfd, sizeof (PIXELFORMATDESCRIPTOR));
  160.     pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR);
  161.     pfd.nVersion = 1;
  162.     pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
  163.     pfd.iPixelType = PFD_TYPE_RGBA;
  164.     pfd.cColorBits = 24;
  165.     pfd.cDepthBits = 16;
  166.     pfd.iLayerType = PFD_MAIN_PLANE;
  167.  
  168.     format = ChoosePixelFormat (ctx->dummy_dc, &pfd);
  169.     SetPixelFormat (ctx->dummy_dc, format, &pfd);
  170.  
  171.     wglMakeCurrent(ctx->dummy_dc, ctx->rc);
  172.  
  173.     return CAIRO_STATUS_SUCCESS;
  174. }
  175.  
  176. cairo_device_t *
  177. cairo_wgl_device_create (HGLRC rc)
  178. {
  179.     cairo_wgl_context_t *ctx;
  180.     cairo_status_t status;
  181.  
  182.     ctx = calloc (1, sizeof (cairo_wgl_context_t));
  183.     if (unlikely (ctx == NULL))
  184.         return _cairo_gl_context_create_in_error (CAIRO_STATUS_NO_MEMORY);
  185.  
  186.     ctx->rc = rc;
  187.     ctx->prev_dc = 0;
  188.     ctx->prev_rc = 0;
  189.  
  190.     status = _wgl_dummy_ctx (ctx);
  191.     if (unlikely (status)) {
  192.         free (ctx);
  193.         return _cairo_gl_context_create_in_error (status);
  194.     }
  195.  
  196.     ctx->base.acquire = _wgl_acquire;
  197.     ctx->base.release = _wgl_release;
  198.     ctx->base.make_current = _wgl_make_current;
  199.     ctx->base.swap_buffers = _wgl_swap_buffers;
  200.     ctx->base.destroy = _wgl_destroy;
  201.  
  202.     status = _cairo_gl_dispatch_init (&ctx->base.dispatch,
  203.                                       (cairo_gl_get_proc_addr_func_t) wglGetProcAddress);
  204.     if (unlikely (status)) {
  205.         free (ctx);
  206.         return _cairo_gl_context_create_in_error (status);
  207.     }
  208.  
  209.     status = _cairo_gl_context_init (&ctx->base);
  210.     if (unlikely (status)) {
  211.         free (ctx);
  212.         return _cairo_gl_context_create_in_error (status);
  213.     }
  214.  
  215.     ctx->base.release (ctx);
  216.  
  217.     return &ctx->base.base;
  218. }
  219.  
  220. HGLRC
  221. cairo_wgl_device_get_context (cairo_device_t *device)
  222. {
  223.     cairo_wgl_context_t *ctx;
  224.  
  225.     if (device->backend->type != CAIRO_DEVICE_TYPE_GL) {
  226.         _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
  227.         return NULL;
  228.     }
  229.  
  230.     ctx = (cairo_wgl_context_t *) device;
  231.  
  232.     return ctx->rc;
  233. }
  234.  
  235. cairo_surface_t *
  236. cairo_gl_surface_create_for_dc (cairo_device_t  *device,
  237.                                 HDC                      dc,
  238.                                 int                      width,
  239.                                 int                      height)
  240. {
  241.     cairo_wgl_surface_t *surface;
  242.  
  243.     if (unlikely (device->status))
  244.         return _cairo_surface_create_in_error (device->status);
  245.  
  246.     if (device->backend->type != CAIRO_DEVICE_TYPE_GL)
  247.         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
  248.  
  249.     if (width <= 0 || height <= 0)
  250.         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
  251.  
  252.     surface = calloc (1, sizeof (cairo_wgl_surface_t));
  253.     if (unlikely (surface == NULL))
  254.         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
  255.  
  256.     _cairo_gl_surface_init (device, &surface->base,
  257.                             CAIRO_CONTENT_COLOR_ALPHA, width, height);
  258.     surface->dc = dc;
  259.  
  260.     return &surface->base.base;
  261. }
  262.