1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci * Copyright 2015 VMware, Inc.
3bf215546Sopenharmony_ci * All Rights Reserved.
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
7bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
8bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
9bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
10bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
11bf215546Sopenharmony_ci * the following conditions:
12bf215546Sopenharmony_ci *
13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
14bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
15bf215546Sopenharmony_ci * of the Software.
16bf215546Sopenharmony_ci *
17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24bf215546Sopenharmony_ci *
25bf215546Sopenharmony_ci **************************************************************************/
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include <windows.h>
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#define WGL_WGLEXT_PROTOTYPES
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci#include <GL/gl.h>
32bf215546Sopenharmony_ci#include <GL/wglext.h>
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#include "state_tracker/st_copytex.h"
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci#include "pipe/p_defines.h"
37bf215546Sopenharmony_ci#include "pipe/p_screen.h"
38bf215546Sopenharmony_ci#include "pipe/p_state.h"
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci#include "gldrv.h"
41bf215546Sopenharmony_ci#include "stw_context.h"
42bf215546Sopenharmony_ci#include "stw_device.h"
43bf215546Sopenharmony_ci#include "stw_pixelformat.h"
44bf215546Sopenharmony_ci#include "stw_framebuffer.h"
45bf215546Sopenharmony_ci#include "stw_st.h"
46bf215546Sopenharmony_ci
47bf215546Sopenharmony_ci
48bf215546Sopenharmony_ci/** Translate a WGL buffer name to a GLenum */
49bf215546Sopenharmony_cistatic GLenum
50bf215546Sopenharmony_citranslate_ibuffer(int iBuffer)
51bf215546Sopenharmony_ci{
52bf215546Sopenharmony_ci   switch (iBuffer) {
53bf215546Sopenharmony_ci   case WGL_FRONT_LEFT_ARB:
54bf215546Sopenharmony_ci      return GL_FRONT_LEFT;
55bf215546Sopenharmony_ci   case WGL_BACK_LEFT_ARB:
56bf215546Sopenharmony_ci      return GL_BACK_LEFT;
57bf215546Sopenharmony_ci   case WGL_FRONT_RIGHT_ARB:
58bf215546Sopenharmony_ci      return GL_FRONT_RIGHT;
59bf215546Sopenharmony_ci   case WGL_BACK_RIGHT_ARB:
60bf215546Sopenharmony_ci      return GL_BACK_RIGHT;
61bf215546Sopenharmony_ci   case WGL_AUX0_ARB:
62bf215546Sopenharmony_ci      return GL_AUX0;
63bf215546Sopenharmony_ci   default:
64bf215546Sopenharmony_ci      return GL_NONE;
65bf215546Sopenharmony_ci   }
66bf215546Sopenharmony_ci}
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci/** Translate a WGL texture target type to a GLenum */
70bf215546Sopenharmony_cistatic GLenum
71bf215546Sopenharmony_citranslate_target(unsigned textureTarget)
72bf215546Sopenharmony_ci{
73bf215546Sopenharmony_ci   switch (textureTarget) {
74bf215546Sopenharmony_ci   case WGL_TEXTURE_1D_ARB:
75bf215546Sopenharmony_ci      return GL_TEXTURE_1D;
76bf215546Sopenharmony_ci   case WGL_TEXTURE_2D_ARB:
77bf215546Sopenharmony_ci      return GL_TEXTURE_2D;
78bf215546Sopenharmony_ci   case WGL_TEXTURE_CUBE_MAP_ARB:
79bf215546Sopenharmony_ci      return GL_TEXTURE_CUBE_MAP;
80bf215546Sopenharmony_ci   case WGL_NO_TEXTURE_ARB:
81bf215546Sopenharmony_ci   default:
82bf215546Sopenharmony_ci      return GL_NONE;
83bf215546Sopenharmony_ci   }
84bf215546Sopenharmony_ci}
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci/** Translate a WGL texture format to a GLenum */
88bf215546Sopenharmony_cistatic GLenum
89bf215546Sopenharmony_citranslate_texture_format(unsigned wgl_format)
90bf215546Sopenharmony_ci{
91bf215546Sopenharmony_ci   switch (wgl_format) {
92bf215546Sopenharmony_ci   case WGL_TEXTURE_RGB_ARB:
93bf215546Sopenharmony_ci      return GL_RGB;
94bf215546Sopenharmony_ci   case WGL_TEXTURE_RGBA_ARB:
95bf215546Sopenharmony_ci      return GL_RGBA;
96bf215546Sopenharmony_ci   case WGL_NO_TEXTURE_ARB:
97bf215546Sopenharmony_ci   default:
98bf215546Sopenharmony_ci      return GL_NONE;
99bf215546Sopenharmony_ci   }
100bf215546Sopenharmony_ci}
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ciBOOL WINAPI
104bf215546Sopenharmony_ciwglBindTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
105bf215546Sopenharmony_ci{
106bf215546Sopenharmony_ci   struct stw_context *curctx = stw_current_context();
107bf215546Sopenharmony_ci   struct stw_framebuffer *fb, *old_fb, *old_fbRead;
108bf215546Sopenharmony_ci   GLenum texFormat, srcBuffer, target;
109bf215546Sopenharmony_ci   boolean retVal;
110bf215546Sopenharmony_ci   int pixelFormatSave;
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_ci   /*
113bf215546Sopenharmony_ci    * Implementation notes:
114bf215546Sopenharmony_ci    * Ideally, we'd implement this function with the
115bf215546Sopenharmony_ci    * st_context_iface::teximage() function which replaces a specific
116bf215546Sopenharmony_ci    * texture image with a different resource (the pbuffer).
117bf215546Sopenharmony_ci    * The main problem however, is the pbuffer image is upside down relative
118bf215546Sopenharmony_ci    * to the texture image.
119bf215546Sopenharmony_ci    * Window system drawing surfaces (windows & pbuffers) are "top to bottom"
120bf215546Sopenharmony_ci    * while OpenGL texture images are "bottom to top".  One possible solution
121bf215546Sopenharmony_ci    * to this is to invert rendering to pbuffers (as we do for renderbuffers)
122bf215546Sopenharmony_ci    * but that could lead to other issues (and would require extensive
123bf215546Sopenharmony_ci    * testing).
124bf215546Sopenharmony_ci    *
125bf215546Sopenharmony_ci    * The simple alternative is to use a copy-based approach which copies the
126bf215546Sopenharmony_ci    * pbuffer image into the texture via glCopyTex[Sub]Image.  That's what
127bf215546Sopenharmony_ci    * we do here.
128bf215546Sopenharmony_ci    */
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci   if (!curctx) {
131bf215546Sopenharmony_ci      debug_printf("No rendering context in wglBindTexImageARB()\n");
132bf215546Sopenharmony_ci      SetLastError(ERROR_INVALID_OPERATION);
133bf215546Sopenharmony_ci      return FALSE;
134bf215546Sopenharmony_ci   }
135bf215546Sopenharmony_ci
136bf215546Sopenharmony_ci   fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);
137bf215546Sopenharmony_ci   if (!fb) {
138bf215546Sopenharmony_ci      debug_printf("Invalid pbuffer handle in wglBindTexImageARB()\n");
139bf215546Sopenharmony_ci      SetLastError(ERROR_INVALID_HANDLE);
140bf215546Sopenharmony_ci      return FALSE;
141bf215546Sopenharmony_ci   }
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   srcBuffer = translate_ibuffer(iBuffer);
144bf215546Sopenharmony_ci   if (srcBuffer == GL_NONE) {
145bf215546Sopenharmony_ci      debug_printf("Invalid buffer 0x%x in wglBindTexImageARB()\n", iBuffer);
146bf215546Sopenharmony_ci      SetLastError(ERROR_INVALID_DATA);
147bf215546Sopenharmony_ci      return FALSE;
148bf215546Sopenharmony_ci   }
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   target = translate_target(fb->textureTarget);
151bf215546Sopenharmony_ci   if (target == GL_NONE) {
152bf215546Sopenharmony_ci      debug_printf("no texture target in wglBindTexImageARB()\n");
153bf215546Sopenharmony_ci      return FALSE;
154bf215546Sopenharmony_ci   }
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   texFormat = translate_texture_format(fb->textureFormat);
157bf215546Sopenharmony_ci   if (texFormat == GL_NONE) {
158bf215546Sopenharmony_ci      debug_printf("no texture format in wglBindTexImageARB()\n");
159bf215546Sopenharmony_ci      return FALSE;
160bf215546Sopenharmony_ci   }
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   old_fb = curctx->current_framebuffer;
163bf215546Sopenharmony_ci   old_fbRead = curctx->current_read_framebuffer;
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci   /*
166bf215546Sopenharmony_ci    * Bind the pbuffer surface so we can read/copy from it.
167bf215546Sopenharmony_ci    *
168bf215546Sopenharmony_ci    * Before we can call stw_make_current() we have to temporarily
169bf215546Sopenharmony_ci    * change the pbuffer's pixel format to match the context to avoid
170bf215546Sopenharmony_ci    * an error condition.  After the stw_make_current() we restore the
171bf215546Sopenharmony_ci    * buffer's pixel format.
172bf215546Sopenharmony_ci    */
173bf215546Sopenharmony_ci   pixelFormatSave = fb->iPixelFormat;
174bf215546Sopenharmony_ci   fb->iPixelFormat = curctx->iPixelFormat;
175bf215546Sopenharmony_ci   retVal = stw_make_current(fb, fb, curctx);
176bf215546Sopenharmony_ci   fb->iPixelFormat = pixelFormatSave;
177bf215546Sopenharmony_ci   if (!retVal) {
178bf215546Sopenharmony_ci      debug_printf("stw_make_current(#1) failed in wglBindTexImageARB()\n");
179bf215546Sopenharmony_ci      return FALSE;
180bf215546Sopenharmony_ci   }
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci   st_copy_framebuffer_to_texture(srcBuffer, fb->width, fb->height,
183bf215546Sopenharmony_ci                                  target, fb->textureLevel,
184bf215546Sopenharmony_ci                                  fb->textureFace, texFormat);
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci   /* rebind previous drawing surface */
187bf215546Sopenharmony_ci   retVal = stw_make_current(old_fb, old_fbRead, curctx);
188bf215546Sopenharmony_ci   if (!retVal) {
189bf215546Sopenharmony_ci      debug_printf("stw_make_current(#2) failed in wglBindTexImageARB()\n");
190bf215546Sopenharmony_ci   }
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci   return retVal;
193bf215546Sopenharmony_ci}
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ciBOOL WINAPI
197bf215546Sopenharmony_ciwglReleaseTexImageARB(HPBUFFERARB hPbuffer, int iBuffer)
198bf215546Sopenharmony_ci{
199bf215546Sopenharmony_ci   struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);
200bf215546Sopenharmony_ci   GLenum srcBuffer;
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   /* nothing to do here, but we do error checking anyway */
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   if (!fb) {
205bf215546Sopenharmony_ci      debug_printf("Invalid pbuffer handle in wglReleaseTexImageARB()\n");
206bf215546Sopenharmony_ci      SetLastError(ERROR_INVALID_HANDLE);
207bf215546Sopenharmony_ci      return FALSE;
208bf215546Sopenharmony_ci   }
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci   srcBuffer = translate_ibuffer(iBuffer);
211bf215546Sopenharmony_ci   if (srcBuffer == GL_NONE) {
212bf215546Sopenharmony_ci      debug_printf("Invalid buffer 0x%x in wglReleaseTexImageARB()\n", iBuffer);
213bf215546Sopenharmony_ci      SetLastError(ERROR_INVALID_DATA);
214bf215546Sopenharmony_ci      return FALSE;
215bf215546Sopenharmony_ci   }
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci   return TRUE;
218bf215546Sopenharmony_ci}
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ciBOOL WINAPI
222bf215546Sopenharmony_ciwglSetPbufferAttribARB(HPBUFFERARB hPbuffer, const int *piAttribList)
223bf215546Sopenharmony_ci{
224bf215546Sopenharmony_ci   struct stw_framebuffer *fb = stw_framebuffer_from_HPBUFFERARB(hPbuffer);
225bf215546Sopenharmony_ci   int face, i;
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci   if (!fb) {
228bf215546Sopenharmony_ci      SetLastError(ERROR_INVALID_HANDLE);
229bf215546Sopenharmony_ci      return FALSE;
230bf215546Sopenharmony_ci   }
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ci   for (i = 0; piAttribList[i]; i += 2) {
233bf215546Sopenharmony_ci      switch (piAttribList[i]) {
234bf215546Sopenharmony_ci      case WGL_MIPMAP_LEVEL_ARB:
235bf215546Sopenharmony_ci         fb->textureLevel = piAttribList[i+1];
236bf215546Sopenharmony_ci         break;
237bf215546Sopenharmony_ci      case WGL_CUBE_MAP_FACE_ARB:
238bf215546Sopenharmony_ci         face = piAttribList[i+1];
239bf215546Sopenharmony_ci         if (face >= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
240bf215546Sopenharmony_ci             face <= WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
241bf215546Sopenharmony_ci            fb->textureFace = face - WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
242bf215546Sopenharmony_ci         }
243bf215546Sopenharmony_ci         else {
244bf215546Sopenharmony_ci            debug_printf("Invalid cube face 0x%x in "
245bf215546Sopenharmony_ci                         "wglSetPbufferAttribARB()\n",
246bf215546Sopenharmony_ci                         piAttribList[i]);
247bf215546Sopenharmony_ci            SetLastError(ERROR_INVALID_DATA);
248bf215546Sopenharmony_ci            return FALSE;
249bf215546Sopenharmony_ci         }
250bf215546Sopenharmony_ci         break;
251bf215546Sopenharmony_ci      default:
252bf215546Sopenharmony_ci         debug_printf("Invalid attribute 0x%x in wglSetPbufferAttribARB()\n",
253bf215546Sopenharmony_ci                      piAttribList[i]);
254bf215546Sopenharmony_ci         SetLastError(ERROR_INVALID_DATA);
255bf215546Sopenharmony_ci         return FALSE;
256bf215546Sopenharmony_ci      }
257bf215546Sopenharmony_ci   }
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci   return TRUE;
260bf215546Sopenharmony_ci}
261