2 * Windows (Win32/Win64) device driver for Mesa
12 #include "pipe/p_winsys.h"
13 #include "pipe/p_format.h"
14 #include "pipe/p_context.h"
15 #include "pipe/p_inlines.h"
16 #include "util/u_memory.h"
17 #include "softpipe/sp_winsys.h"
18 #include "glapi/glapi.h"
22 _mesa_create_visual( GLboolean rgbFlag
,
38 /* linked list of our Framebuffers (windows) */
39 WMesaFramebuffer FirstFramebuffer
= NULL
;
41 struct wmesa_pipe_winsys
43 struct pipe_winsys base
;
47 * Choose the pixel format for the given visual.
48 * This will tell the gallium driver how to pack pixel data into
52 choose_pixel_format(GLvisual
*v
)
55 return PIPE_FORMAT_A8R8G8B8_UNORM
;
57 if ( GET_REDMASK(v
) == 0x0000ff
58 && GET_GREENMASK(v
) == 0x00ff00
59 && GET_BLUEMASK(v
) == 0xff0000
60 && v
->BitsPerPixel
== 32) {
61 if (CHECK_BYTE_ORDER(v
)) {
62 /* no byteswapping needed */
63 return 0 /* PIXEL_FORMAT_U_A8_B8_G8_R8 */;
66 return PIPE_FORMAT_R8G8B8A8_UNORM
;
69 else if ( GET_REDMASK(v
) == 0xff0000
70 && GET_GREENMASK(v
) == 0x00ff00
71 && GET_BLUEMASK(v
) == 0x0000ff
72 && v
->BitsPerPixel
== 32) {
73 if (CHECK_BYTE_ORDER(v
)) {
74 /* no byteswapping needed */
75 return PIPE_FORMAT_A8R8G8B8_UNORM
;
78 return PIPE_FORMAT_B8G8R8A8_UNORM
;
81 else if ( GET_REDMASK(v
) == 0xf800
82 && GET_GREENMASK(v
) == 0x07e0
83 && GET_BLUEMASK(v
) == 0x001f
84 && CHECK_BYTE_ORDER(v
)
85 && v
->BitsPerPixel
== 16) {
87 return PIPE_FORMAT_R5G6B5_UNORM
;
90 printf("BITS %d\n",v
->BitsPerPixel
);
97 * Determine the pixel format based on the pixel size.
99 static void wmSetPixelFormat(WMesaFramebuffer pwfb
, HDC hDC
)
101 /* Only 16 and 32 bit targets are supported now */
102 assert(pwfb
->cColorBits
== 0 ||
103 pwfb
->cColorBits
== 16 ||
104 pwfb
->cColorBits
== 32);
106 switch(pwfb
->cColorBits
){
108 pwfb
->pixelformat
= PF_INDEX8
;
111 pwfb
->pixelformat
= PF_5R6G5B
;
114 pwfb
->pixelformat
= PF_8R8G8B
;
117 pwfb
->pixelformat
= PF_BADFORMAT
;
122 * Create a new WMesaFramebuffer object which will correspond to the
123 * given HDC (Window handle).
126 wmesa_new_framebuffer(HDC hdc
, GLvisual
*visual
, GLuint width
, GLuint height
)
128 WMesaFramebuffer pwfb
129 = (WMesaFramebuffer
) malloc(sizeof(struct wmesa_framebuffer
));
131 enum pipe_format colorFormat
, depthFormat
, stencilFormat
;
133 /* determine PIPE_FORMATs for buffers */
134 colorFormat
= choose_pixel_format(visual
);
136 if (visual
->depthBits
== 0)
137 depthFormat
= PIPE_FORMAT_NONE
;
138 else if (visual
->depthBits
<= 16)
139 depthFormat
= PIPE_FORMAT_Z16_UNORM
;
140 else if (visual
->depthBits
<= 24)
141 depthFormat
= PIPE_FORMAT_S8Z24_UNORM
;
143 depthFormat
= PIPE_FORMAT_Z32_UNORM
;
145 if (visual
->stencilBits
== 8) {
146 if (depthFormat
== PIPE_FORMAT_S8Z24_UNORM
)
147 stencilFormat
= depthFormat
;
149 stencilFormat
= PIPE_FORMAT_S8_UNORM
;
152 stencilFormat
= PIPE_FORMAT_NONE
;
155 pwfb
->stfb
= st_create_framebuffer(visual
,
156 colorFormat
, depthFormat
, stencilFormat
,
160 pwfb
->cColorBits
= GetDeviceCaps(hdc
, BITSPIXEL
);
163 /* insert at head of list */
164 pwfb
->next
= FirstFramebuffer
;
165 FirstFramebuffer
= pwfb
;
171 * Given an hdc, free the corresponding WMesaFramebuffer
174 wmesa_free_framebuffer(HDC hdc
)
176 WMesaFramebuffer pwfb
, prev
;
177 for (pwfb
= FirstFramebuffer
; pwfb
; pwfb
= pwfb
->next
) {
178 if (pwfb
->hDC
== hdc
)
183 if (pwfb
== FirstFramebuffer
)
184 FirstFramebuffer
= pwfb
->next
;
186 prev
->next
= pwfb
->next
;
192 * Given an hdc, return the corresponding WMesaFramebuffer
195 wmesa_lookup_framebuffer(HDC hdc
)
197 WMesaFramebuffer pwfb
;
198 for (pwfb
= FirstFramebuffer
; pwfb
; pwfb
= pwfb
->next
) {
199 if (pwfb
->hDC
== hdc
)
207 * Given a GLframebuffer, return the corresponding WMesaFramebuffer.
209 static WMesaFramebuffer
wmesa_framebuffer(GLframebuffer
*fb
)
211 return (WMesaFramebuffer
) fb
;
216 * Given a GLcontext, return the corresponding WMesaContext.
218 static WMesaContext
wmesa_context(const GLcontext
*ctx
)
220 return (WMesaContext
) ctx
;
224 * Find the width and height of the window named by hdc.
227 get_window_size(HDC hdc
, GLuint
*width
, GLuint
*height
)
229 if (WindowFromDC(hdc
)) {
231 GetClientRect(WindowFromDC(hdc
), &rect
);
232 *width
= rect
.right
- rect
.left
;
233 *height
= rect
.bottom
- rect
.top
;
235 else { /* Memory context */
236 /* From contributed code - use the size of the desktop
237 * for the size of a memory context (?) */
238 *width
= GetDeviceCaps(hdc
, HORZRES
);
239 *height
= GetDeviceCaps(hdc
, VERTRES
);
244 * Low-level OS/window system memory buffer
248 struct pipe_buffer base
;
249 boolean userBuffer
; /** Is this a user-space buffer? */
256 struct pipe_surface surface
;
263 static INLINE
struct wmesa_surface
*
264 wmesa_surface(struct pipe_surface
*ps
)
267 return (struct wmesa_surface
*) ps
;
271 * Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque
274 static INLINE
struct wm_buffer
*
275 wm_buffer( struct pipe_buffer
*buf
)
277 return (struct wm_buffer
*)buf
;
282 /* Most callbacks map direcly onto dri_bufmgr operations:
285 wm_buffer_map(struct pipe_winsys
*pws
, struct pipe_buffer
*buf
,
288 struct wm_buffer
*wm_buf
= wm_buffer(buf
);
289 wm_buf
->mapped
= wm_buf
->data
;
290 return wm_buf
->mapped
;
294 wm_buffer_unmap(struct pipe_winsys
*pws
, struct pipe_buffer
*buf
)
296 struct wm_buffer
*wm_buf
= wm_buffer(buf
);
297 wm_buf
->mapped
= NULL
;
301 wm_buffer_destroy(struct pipe_winsys
*pws
,
302 struct pipe_buffer
*buf
)
304 struct wm_buffer
*oldBuf
= wm_buffer(buf
);
308 if (!oldBuf
->userBuffer
) {
309 align_free(oldBuf
->data
);
321 wm_flush_frontbuffer(struct pipe_winsys
*pws
,
322 struct pipe_surface
*surf
,
323 void *context_private
)
325 WMesaContext pwc
= context_private
;
326 WMesaFramebuffer pwfb
= wmesa_lookup_framebuffer(pwc
->hDC
);
327 struct wm_buffer
*wm_buf
;
328 BITMAPINFO bmi
, *pbmi
;
330 wm_buf
= wm_buffer(surf
->buffer
);
333 memset(pbmi
, 0, sizeof(BITMAPINFO
));
334 pbmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
335 pbmi
->bmiHeader
.biWidth
= pwfb
->stfb
->Base
.Width
;
336 pbmi
->bmiHeader
.biHeight
= -((long)pwfb
->stfb
->Base
.Height
);
337 pbmi
->bmiHeader
.biPlanes
= 1;
338 pbmi
->bmiHeader
.biBitCount
= pwfb
->cColorBits
;
339 pbmi
->bmiHeader
.biCompression
= BI_RGB
;
340 pbmi
->bmiHeader
.biSizeImage
= 0;
341 pbmi
->bmiHeader
.biXPelsPerMeter
= 0;
342 pbmi
->bmiHeader
.biYPelsPerMeter
= 0;
343 pbmi
->bmiHeader
.biClrUsed
= 0;
344 pbmi
->bmiHeader
.biClrImportant
= 0;
346 StretchDIBits(pwfb
->hDC
, 0, 0, pwfb
->stfb
->Base
.Width
, pwfb
->stfb
->Base
.Height
, 0, 0, pwfb
->stfb
->Base
.Width
, pwfb
->stfb
->Base
.Height
, wm_buf
->data
, pbmi
, 0, SRCCOPY
);
352 wm_get_name(struct pipe_winsys
*pws
)
357 static struct pipe_buffer
*
358 wm_buffer_create(struct pipe_winsys
*pws
,
363 struct wm_buffer
*buffer
= CALLOC_STRUCT(wm_buffer
);
365 buffer
->base
.refcount
= 1;
366 buffer
->base
.alignment
= alignment
;
367 buffer
->base
.usage
= usage
;
368 buffer
->base
.size
= size
;
370 if (buffer
->data
== NULL
) {
371 /* align to 16-byte multiple for Cell */
372 buffer
->data
= align_malloc(size
, max(alignment
, 16));
375 return &buffer
->base
;
380 * Create buffer which wraps user-space data.
382 static struct pipe_buffer
*
383 wm_user_buffer_create(struct pipe_winsys
*pws
, void *ptr
, unsigned bytes
)
385 struct wm_buffer
*buffer
= CALLOC_STRUCT(wm_buffer
);
386 buffer
->base
.refcount
= 1;
387 buffer
->base
.size
= bytes
;
388 buffer
->userBuffer
= TRUE
;
391 return &buffer
->base
;
397 * Round n up to next multiple.
399 static INLINE
unsigned
400 round_up(unsigned n
, unsigned multiple
)
402 return (n
+ multiple
- 1) & ~(multiple
- 1);
406 wm_surface_alloc_storage(struct pipe_winsys
*winsys
,
407 struct pipe_surface
*surf
,
408 unsigned width
, unsigned height
,
409 enum pipe_format format
,
413 const unsigned alignment
= 64;
416 surf
->height
= height
;
417 surf
->format
= format
;
418 pf_get_block(format
, &surf
->block
);
419 surf
->nblocksx
= pf_get_nblocksx(&surf
->block
, width
);
420 surf
->nblocksy
= pf_get_nblocksy(&surf
->block
, height
);
421 surf
->stride
= round_up(surf
->nblocksx
* surf
->block
.size
, alignment
);
423 assert(!surf
->buffer
);
424 surf
->buffer
= winsys
->buffer_create(winsys
, alignment
,
425 PIPE_BUFFER_USAGE_PIXEL
,
426 surf
->nblocksy
* surf
->stride
);
435 * Called via winsys->surface_alloc() to create new surfaces.
437 static struct pipe_surface
*
438 wm_surface_alloc(struct pipe_winsys
*ws
)
440 struct wmesa_surface
*wms
= CALLOC_STRUCT(wmesa_surface
);
441 static boolean no_swap
= 0;
442 static boolean firsttime
= 1;
445 no_swap
= getenv("SP_NO_RAST") != NULL
;
451 wms
->surface
.refcount
= 1;
452 wms
->surface
.winsys
= ws
;
454 wms
->no_swap
= no_swap
;
456 return &wms
->surface
;
460 wm_surface_release(struct pipe_winsys
*winsys
, struct pipe_surface
**s
)
462 struct pipe_surface
*surf
= *s
;
464 if (surf
->refcount
== 0) {
466 winsys_buffer_reference(winsys
, &surf
->buffer
, NULL
);
474 * Fence functions - basically nothing to do, as we don't create any actual
479 wm_fence_reference(struct pipe_winsys
*sws
, struct pipe_fence_handle
**ptr
,
480 struct pipe_fence_handle
*fence
)
486 wm_fence_signalled(struct pipe_winsys
*sws
, struct pipe_fence_handle
*fence
,
494 wm_fence_finish(struct pipe_winsys
*sws
, struct pipe_fence_handle
*fence
,
503 wmesa_get_pipe_winsys(GLvisual
*visual
)
505 static struct wmesa_pipe_winsys
*ws
= NULL
;
508 ws
= CALLOC_STRUCT(wmesa_pipe_winsys
);
510 /* Fill in this struct with callbacks that pipe will need to
511 * communicate with the window system, buffer manager, etc.
513 ws
->base
.buffer_create
= wm_buffer_create
;
514 ws
->base
.user_buffer_create
= wm_user_buffer_create
;
515 ws
->base
.buffer_map
= wm_buffer_map
;
516 ws
->base
.buffer_unmap
= wm_buffer_unmap
;
517 ws
->base
.buffer_destroy
= wm_buffer_destroy
;
519 ws
->base
.surface_alloc
= wm_surface_alloc
;
520 ws
->base
.surface_alloc_storage
= wm_surface_alloc_storage
;
521 ws
->base
.surface_release
= wm_surface_release
;
523 ws
->base
.fence_reference
= wm_fence_reference
;
524 ws
->base
.fence_signalled
= wm_fence_signalled
;
525 ws
->base
.fence_finish
= wm_fence_finish
;
527 ws
->base
.flush_frontbuffer
= wm_flush_frontbuffer
;
528 ws
->base
.get_name
= wm_get_name
;
536 /**********************************************************************/
537 /***** WMESA Functions *****/
538 /**********************************************************************/
540 WMesaContext
WMesaCreateContext(HDC hDC
,
544 GLboolean alpha_flag
)
547 struct pipe_winsys
*pws
;
548 struct pipe_context
*pipe
;
549 struct pipe_screen
*screen
;
550 GLint red_bits
, green_bits
, blue_bits
, alpha_bits
;
555 /* Indexed mode not supported */
559 /* Allocate wmesa context */
560 c
= CALLOC_STRUCT(wmesa_context
);
566 /* Get data for visual */
567 /* Dealing with this is actually a bit of overkill because Mesa will end
568 * up treating all color component size requests less than 8 by using
569 * a single byte per channel. In addition, the interface to the span
570 * routines passes colors as an entire byte per channel anyway, so there
571 * is nothing to be saved by telling the visual to be 16 bits if the device
572 * is 16 bits. That is, Mesa is going to compute colors down to 8 bits per
574 * But we go through the motions here anyway.
576 c
->cColorBits
= GetDeviceCaps(c
->hDC
, BITSPIXEL
);
578 switch (c
->cColorBits
) {
580 red_bits
= green_bits
= blue_bits
= 5;
584 red_bits
= green_bits
= blue_bits
= 8;
588 /* Create visual based on flags */
589 visual
= _mesa_create_visual(rgb_flag
,
590 db_flag
, /* db_flag */
591 GL_FALSE
, /* stereo */
592 red_bits
, green_bits
, blue_bits
, /* color RGB */
593 alpha_flag
? alpha_bits
: 0, /* color A */
595 DEFAULT_SOFTWARE_DEPTH_BITS
, /* depth_bits */
596 8, /* stencil_bits */
597 16,16,16, /* accum RGB */
598 alpha_flag
? 16 : 0, /* accum A */
599 1); /* num samples */
606 pws
= wmesa_get_pipe_winsys(visual
);
608 screen
= softpipe_create_screen(pws
);
615 pipe
= softpipe_create(screen
, pws
, NULL
);
618 /* FIXME - free screen */
625 c
->st
= st_create_context(pipe
, visual
, NULL
);
627 c
->st
->ctx
->DriverCtx
= c
;
633 void WMesaDestroyContext( WMesaContext pwc
)
635 GLcontext
*ctx
= pwc
->st
->ctx
;
636 WMesaFramebuffer pwfb
;
637 GET_CURRENT_CONTEXT(cur_ctx
);
639 if (cur_ctx
== ctx
) {
640 /* unbind current if deleting current context */
641 WMesaMakeCurrent(NULL
, NULL
);
644 /* clean up frame buffer resources */
645 pwfb
= wmesa_lookup_framebuffer(pwc
->hDC
);
647 wmesa_free_framebuffer(pwc
->hDC
);
650 /* Release for device, not memory contexts */
651 if (WindowFromDC(pwc
->hDC
) != NULL
)
653 ReleaseDC(WindowFromDC(pwc
->hDC
), pwc
->hDC
);
656 st_destroy_context(pwc
->st
);
661 void WMesaMakeCurrent(WMesaContext c
, HDC hdc
)
663 GLuint width
= 0, height
= 0;
664 WMesaFramebuffer pwfb
;
667 /* return if already current */
668 GET_CURRENT_CONTEXT(ctx
);
669 WMesaContext pwc
= wmesa_context(ctx
);
670 if (pwc
&& c
== pwc
&& pwc
->hDC
== hdc
)
674 pwfb
= wmesa_lookup_framebuffer(hdc
);
677 get_window_size(hdc
, &width
, &height
);
680 /* Lazy creation of framebuffers */
681 if (c
&& !pwfb
&& (hdc
!= 0)) {
682 GLvisual
*visual
= &c
->st
->ctx
->Visual
;
684 pwfb
= wmesa_new_framebuffer(hdc
, visual
, width
, height
);
688 st_make_current(c
->st
, pwfb
->stfb
, pwfb
->stfb
);
690 st_resize_framebuffer(pwfb
->stfb
, width
, height
);
694 st_make_current( NULL
, NULL
, NULL
);
699 void WMesaSwapBuffers( HDC hdc
)
701 struct pipe_surface
*surf
;
702 struct wm_buffer
*wm_buf
;
703 WMesaFramebuffer pwfb
= wmesa_lookup_framebuffer(hdc
);
704 BITMAPINFO bmi
, *pbmi
;
707 _mesa_problem(NULL
, "wmesa: swapbuffers on unknown hdc");
712 /* If we're swapping the buffer associated with the current context
713 * we have to flush any pending rendering commands first.
715 st_notify_swapbuffers(pwfb
->stfb
);
717 surf
= st_get_framebuffer_surface(pwfb
->stfb
, ST_SURFACE_BACK_LEFT
);
718 wm_buf
= wm_buffer(surf
->buffer
);
721 memset(pbmi
, 0, sizeof(BITMAPINFO
));
722 pbmi
->bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
723 pbmi
->bmiHeader
.biWidth
= pwfb
->stfb
->Base
.Width
;
724 pbmi
->bmiHeader
.biHeight
= -((long)pwfb
->stfb
->Base
.Height
);
725 pbmi
->bmiHeader
.biPlanes
= 1;
726 pbmi
->bmiHeader
.biBitCount
= pwfb
->cColorBits
;
727 pbmi
->bmiHeader
.biCompression
= BI_RGB
;
728 pbmi
->bmiHeader
.biSizeImage
= 0;
729 pbmi
->bmiHeader
.biXPelsPerMeter
= 0;
730 pbmi
->bmiHeader
.biYPelsPerMeter
= 0;
731 pbmi
->bmiHeader
.biClrUsed
= 0;
732 pbmi
->bmiHeader
.biClrImportant
= 0;
734 StretchDIBits(pwfb
->hDC
, 0, 0, pwfb
->stfb
->Base
.Width
, pwfb
->stfb
->Base
.Height
, 0, 0, pwfb
->stfb
->Base
.Width
, pwfb
->stfb
->Base
.Height
, wm_buf
->data
, pbmi
, 0, SRCCOPY
);
737 GLuint width
= 0, height
= 0;
739 get_window_size(pwfb
->hDC
, &width
, &height
);
741 st_resize_framebuffer(pwfb
->stfb
, width
, height
);
745 /* This is hopefully a temporary hack to define some needed dispatch
746 * table entries. Hopefully, I'll find a better solution. The
747 * dispatch table generation scripts ought to be making these dummy
749 #if !defined(__MINGW32__) || !defined(GL_NO_STDCALL)
750 void gl_dispatch_stub_543(void){}
751 void gl_dispatch_stub_544(void){}
752 void gl_dispatch_stub_545(void){}
753 void gl_dispatch_stub_546(void){}
754 void gl_dispatch_stub_547(void){}
755 void gl_dispatch_stub_548(void){}
756 void gl_dispatch_stub_549(void){}
757 void gl_dispatch_stub_550(void){}
758 void gl_dispatch_stub_551(void){}
759 void gl_dispatch_stub_552(void){}
760 void gl_dispatch_stub_553(void){}
761 void gl_dispatch_stub_554(void){}
762 void gl_dispatch_stub_555(void){}
763 void gl_dispatch_stub_556(void){}
764 void gl_dispatch_stub_557(void){}
765 void gl_dispatch_stub_558(void){}
766 void gl_dispatch_stub_559(void){}
767 void gl_dispatch_stub_560(void){}
768 void gl_dispatch_stub_561(void){}
769 void gl_dispatch_stub_565(void){}
770 void gl_dispatch_stub_566(void){}
771 void gl_dispatch_stub_577(void){}
772 void gl_dispatch_stub_578(void){}
773 void gl_dispatch_stub_603(void){}
774 void gl_dispatch_stub_645(void){}
775 void gl_dispatch_stub_646(void){}
776 void gl_dispatch_stub_647(void){}
777 void gl_dispatch_stub_648(void){}
778 void gl_dispatch_stub_649(void){}
779 void gl_dispatch_stub_650(void){}
780 void gl_dispatch_stub_651(void){}
781 void gl_dispatch_stub_652(void){}
782 void gl_dispatch_stub_653(void){}
783 void gl_dispatch_stub_733(void){}
784 void gl_dispatch_stub_734(void){}
785 void gl_dispatch_stub_735(void){}
786 void gl_dispatch_stub_736(void){}
787 void gl_dispatch_stub_737(void){}
788 void gl_dispatch_stub_738(void){}
789 void gl_dispatch_stub_744(void){}
790 void gl_dispatch_stub_745(void){}
791 void gl_dispatch_stub_746(void){}
792 void gl_dispatch_stub_760(void){}
793 void gl_dispatch_stub_761(void){}
794 void gl_dispatch_stub_763(void){}
795 void gl_dispatch_stub_765(void){}
796 void gl_dispatch_stub_766(void){}
797 void gl_dispatch_stub_767(void){}
798 void gl_dispatch_stub_768(void){}
800 void gl_dispatch_stub_562(void){}
801 void gl_dispatch_stub_563(void){}
802 void gl_dispatch_stub_564(void){}
803 void gl_dispatch_stub_567(void){}
804 void gl_dispatch_stub_568(void){}
805 void gl_dispatch_stub_569(void){}
806 void gl_dispatch_stub_580(void){}
807 void gl_dispatch_stub_581(void){}
808 void gl_dispatch_stub_606(void){}
809 void gl_dispatch_stub_654(void){}
810 void gl_dispatch_stub_655(void){}
811 void gl_dispatch_stub_656(void){}
812 void gl_dispatch_stub_739(void){}
813 void gl_dispatch_stub_740(void){}
814 void gl_dispatch_stub_741(void){}
815 void gl_dispatch_stub_748(void){}
816 void gl_dispatch_stub_749(void){}
817 void gl_dispatch_stub_769(void){}
818 void gl_dispatch_stub_770(void){}
819 void gl_dispatch_stub_771(void){}
820 void gl_dispatch_stub_772(void){}
821 void gl_dispatch_stub_773(void){}