1/**************************************************************************
2 *
3 * Copyright 2009-2010 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 *
27 **************************************************************************/
28
29/**
30 * @file
31 * Softpipe/LLVMpipe support.
32 *
33 * @author Jose Fonseca <jfonseca@vmware.com>
34 */
35
36
37#include <windows.h>
38
39#include "util/u_debug.h"
40#include "stw_winsys.h"
41#include "stw_device.h"
42#include "gdi/gdi_sw_winsys.h"
43
44#include "softpipe/sp_texture.h"
45#include "softpipe/sp_screen.h"
46#include "softpipe/sp_public.h"
47
48#ifdef HAVE_LLVMPIPE
49#include "llvmpipe/lp_texture.h"
50#include "llvmpipe/lp_screen.h"
51#include "llvmpipe/lp_public.h"
52#endif
53
54#ifdef HAVE_SWR
55#include "swr/swr_public.h"
56#endif
57
58static boolean use_llvmpipe = FALSE;
59static boolean use_swr = FALSE;
60
61static struct pipe_screen *
62gdi_screen_create(void)
63{
64   const char *default_driver;
65   const char *driver;
66   struct pipe_screen *screen = NULL;
67   struct sw_winsys *winsys;
68
69   winsys = gdi_create_sw_winsys();
70   if(!winsys)
71      goto no_winsys;
72
73#ifdef HAVE_LLVMPIPE
74   default_driver = "llvmpipe";
75#elif HAVE_SWR
76   default_driver = "swr";
77#else
78   default_driver = "softpipe";
79#endif
80
81   driver = debug_get_option("GALLIUM_DRIVER", default_driver);
82
83#ifdef HAVE_LLVMPIPE
84   if (strcmp(driver, "llvmpipe") == 0) {
85      screen = llvmpipe_create_screen( winsys );
86      if (screen)
87         use_llvmpipe = TRUE;
88   }
89#endif
90#ifdef HAVE_SWR
91   if (strcmp(driver, "swr") == 0) {
92      screen = swr_create_screen( winsys );
93      if (screen)
94         use_swr = TRUE;
95   }
96#endif
97   (void) driver;
98
99   if (screen == NULL) {
100      screen = softpipe_create_screen( winsys );
101   }
102
103   if(!screen)
104      goto no_screen;
105
106   return screen;
107
108no_screen:
109   winsys->destroy(winsys);
110no_winsys:
111   return NULL;
112}
113
114
115static void
116gdi_present(struct pipe_screen *screen,
117            struct pipe_resource *res,
118            HDC hDC)
119{
120   /* This will fail if any interposing layer (trace, debug, etc) has
121    * been introduced between the state-trackers and the pipe driver.
122    *
123    * Ideally this would get replaced with a call to
124    * pipe_screen::flush_frontbuffer().
125    *
126    * Failing that, it may be necessary for intervening layers to wrap
127    * other structs such as this stw_winsys as well...
128    */
129
130   struct sw_winsys *winsys = NULL;
131   struct sw_displaytarget *dt = NULL;
132
133#ifdef HAVE_LLVMPIPE
134   if (use_llvmpipe) {
135      winsys = llvmpipe_screen(screen)->winsys;
136      dt = llvmpipe_resource(res)->dt;
137      gdi_sw_display(winsys, dt, hDC);
138      return;
139   }
140#endif
141
142#ifdef HAVE_SWR
143   if (use_swr) {
144      swr_gdi_swap(screen, res, hDC);
145      return;
146   }
147#endif
148
149   winsys = softpipe_screen(screen)->winsys,
150   dt = softpipe_resource(res)->dt,
151   gdi_sw_display(winsys, dt, hDC);
152}
153
154
155static const struct stw_winsys stw_winsys = {
156   &gdi_screen_create,
157   &gdi_present,
158   NULL, /* get_adapter_luid */
159   NULL, /* shared_surface_open */
160   NULL, /* shared_surface_close */
161   NULL  /* compose */
162};
163
164
165EXTERN_C BOOL WINAPI
166DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
167
168
169BOOL WINAPI
170DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
171{
172   switch (fdwReason) {
173   case DLL_PROCESS_ATTACH:
174      stw_init(&stw_winsys);
175      stw_init_thread();
176      break;
177
178   case DLL_THREAD_ATTACH:
179      stw_init_thread();
180      break;
181
182   case DLL_THREAD_DETACH:
183      stw_cleanup_thread();
184      break;
185
186   case DLL_PROCESS_DETACH:
187      if (lpvReserved == NULL) {
188         // We're being unloaded from the process.
189         stw_cleanup_thread();
190         stw_cleanup();
191      } else {
192         // Process itself is terminating, and all threads and modules are
193         // being detached.
194         //
195         // The order threads (including llvmpipe rasterizer threads) are
196         // destroyed can not be relied up, so it's not safe to cleanup.
197         //
198         // However global destructors (e.g., LLVM's) will still be called, and
199         // if Microsoft OPENGL32.DLL's DllMain is called after us, it will
200         // still try to invoke DrvDeleteContext to destroys all outstanding,
201         // so set stw_dev to NULL to return immediately if that happens.
202         stw_dev = NULL;
203      }
204      break;
205   }
206   return TRUE;
207}
208