xref: /reactos/dll/opengl/opengl32/swimpl.c (revision f04935d8)
1 /*
2  * COPYRIGHT:            See COPYING in the top level directory
3  * PROJECT:              ReactOS
4  * FILE:                 dll/opengl/opengl32/swimpl.c
5  * PURPOSE:              OpenGL32 DLL, opengl software implementation
6  */
7 
8 #include "opengl32.h"
9 
10 /* MESA includes */
11 #include <context.h>
12 #include <matrix.h>
13 
14 WINE_DEFAULT_DEBUG_CHANNEL(opengl32);
15 
16 #define WIDTH_BYTES_ALIGN32(cx, bpp) ((((cx) * (bpp) + 31) & ~31) >> 3)
17 #define WIDTH_BYTES_ALIGN16(cx, bpp) ((((cx) * (bpp) + 15) & ~15) >> 3)
18 
19 /* Flags for our pixel formats */
20 #define SB_FLAGS            (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT)
21 #define SB_FLAGS_WINDOW     (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT)
22 #define SB_FLAGS_PALETTE    (PFD_DRAW_TO_BITMAP | PFD_SUPPORT_GDI | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT | PFD_NEED_PALETTE)
23 #define DB_FLAGS            (PFD_DOUBLEBUFFER   | PFD_SWAP_COPY   | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT)
24 #define DB_FLAGS_PALETTE    (PFD_DOUBLEBUFFER   | PFD_SWAP_COPY   | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT | PFD_NEED_PALETTE)
25 
26 
27 struct pixel_format
28 {
29     DWORD dwFlags;
30     BYTE iPixelType;
31     BYTE cColorBits;
32     BYTE cRedBits; BYTE cRedShift;
33     BYTE cGreenBits; BYTE cGreenShift;
34     BYTE cBlueBits; BYTE cBlueShift;
35     BYTE cAlphaBits; BYTE cAlphaShift;
36     BYTE cAccumBits;
37     BYTE cAccumRedBits; BYTE cAccumGreenBits; BYTE cAccumBlueBits; BYTE cAccumAlphaBits;
38     BYTE cDepthBits;
39 };
40 
41 static const struct pixel_format pixel_formats_32[] =
42 {
43     /* 32bpp */
44     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  32},
45     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  16},
46     {DB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  32},
47     {DB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  16},
48     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 32},
49     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 16},
50     {DB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 32},
51     {DB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 16},
52     {SB_FLAGS_WINDOW,  PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  32},
53     {SB_FLAGS_WINDOW,  PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  16},
54     {DB_FLAGS,         PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  32},
55     {DB_FLAGS,         PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  16},
56     /* 24bpp */
57     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  32},
58     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  16},
59     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 32},
60     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 16},
61     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  32},
62     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  16},
63     /* 16 bpp */
64     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0,  32},
65     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0,  16},
66     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 8, 0, 32, 8,  8,  8,  8,  32},
67     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 8, 0, 32, 8,  8,  8,  8,  16},
68     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 16, 5, 10, 5, 5, 5, 0, 0, 0, 0,  0,  0,  0,  0,  32},
69     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 16, 5, 10, 5, 5, 5, 0, 0, 0, 0,  0,  0,  0,  0,  16},
70     /* 8bpp */
71     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0,  32},
72     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0,  16},
73     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 8, 0, 32, 8,  8,  8,  8,  32},
74     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 8, 0, 32, 8,  8,  8,  8,  16},
75     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 8,  3, 0,  3, 3, 2, 6, 0, 0, 0,  0,  0,  0,  0,  32},
76     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 8,  3, 0,  3, 3, 2, 6, 0, 0, 0,  0,  0,  0,  0,  16},
77     /* 4bpp */
78     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 0, 0, 16, 5,  6,  5,  0,  32},
79     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 0, 0, 16, 5,  6,  5,  0,  16},
80     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 8, 0, 16, 4,  4,  4,  4,  32},
81     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 8, 0, 16, 4,  4,  4,  4,  16},
82     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 4,  1, 0,  1, 1, 1, 2, 0, 0, 0,  0,  0,  0,  0,  32},
83     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 4,  1, 0,  1, 1, 1, 2, 0, 0, 0,  0,  0,  0,  0,  16},
84 };
85 
86 static const struct pixel_format pixel_formats_24[] =
87 {
88     /* 24bpp */
89     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  32},
90     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  16},
91     {DB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  32},
92     {DB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  16},
93     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 32},
94     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 16},
95     {DB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 32},
96     {DB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 16},
97     {SB_FLAGS_WINDOW,  PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  32},
98     {SB_FLAGS_WINDOW,  PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  16},
99     {DB_FLAGS,         PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  32},
100     {DB_FLAGS,         PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  16},
101     /* 32bpp */
102     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  32},
103     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  16},
104     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 32},
105     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 16},
106     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  32},
107     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  16},
108     /* 16 bpp */
109     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0,  32},
110     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0,  16},
111     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 8, 0, 32, 8,  8,  8,  8,  32},
112     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 8, 0, 32, 8,  8,  8,  8,  16},
113     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 16, 5, 10, 5, 5, 5, 0, 0, 0, 0,  0,  0,  0,  0,  32},
114     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 16, 5, 10, 5, 5, 5, 0, 0, 0, 0,  0,  0,  0,  0,  16},
115     /* 8bpp */
116     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0,  32},
117     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0,  16},
118     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 8, 0, 32, 8,  8,  8,  8,  32},
119     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 8, 0, 32, 8,  8,  8,  8,  16},
120     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 8,  3, 0,  3, 3, 2, 6, 0, 0, 0,  0,  0,  0,  0,  32},
121     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 8,  3, 0,  3, 3, 2, 6, 0, 0, 0,  0,  0,  0,  0,  16},
122     /* 4bpp */
123     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 0, 0, 16, 5,  6,  5,  0,  32},
124     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 0, 0, 16, 5,  6,  5,  0,  16},
125     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 8, 0, 16, 4,  4,  4,  4,  32},
126     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 8, 0, 16, 4,  4,  4,  4,  16},
127     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 4,  1, 0,  1, 1, 1, 2, 0, 0, 0,  0,  0,  0,  0,  32},
128     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 4,  1, 0,  1, 1, 1, 2, 0, 0, 0,  0,  0,  0,  0,  16},
129 };
130 
131 static const struct pixel_format pixel_formats_16[] =
132 {
133     /* 16 bpp - 565 */
134     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       16, 5, 11, 6, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0,  32},
135     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       16, 5, 11, 6, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0,  16},
136     {DB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 11, 6, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0,  32},
137     {DB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 11, 6, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0,  16},
138     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       16, 5, 11, 6, 5, 5, 0, 8, 0, 32, 8,  8,  8,  8,  32},
139     {SB_FLAGS_WINDOW,  PFD_TYPE_RGBA,       16, 5, 11, 6, 5, 5, 0, 8, 0, 32, 8,  8,  8,  8,  16},
140     {DB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 11, 6, 5, 5, 0, 8, 0, 32, 8,  8,  8,  8,  32},
141     {DB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 11, 6, 5, 5, 0, 8, 0, 32, 8,  8,  8,  8,  16},
142     {SB_FLAGS_WINDOW,  PFD_TYPE_COLORINDEX, 16, 5, 11, 6, 5, 5, 0, 0, 0, 0,  0,  0,  0,  0,  32},
143     {SB_FLAGS_WINDOW,  PFD_TYPE_COLORINDEX, 16, 5, 11, 6, 5, 5, 0, 0, 0, 0,  0,  0,  0,  0,  16},
144     {DB_FLAGS,         PFD_TYPE_COLORINDEX, 16, 5, 11, 6, 5, 5, 0, 0, 0, 0,  0,  0,  0,  0,  32},
145     {DB_FLAGS,         PFD_TYPE_COLORINDEX, 16, 5, 11, 6, 5, 5, 0, 0, 0, 0,  0,  0,  0,  0,  16},
146     /* 24bpp */
147     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  32},
148     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  16},
149     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 32},
150     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 16},
151     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  32},
152     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  16},
153     /* 32bpp */
154     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  32},
155     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  16},
156     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 32},
157     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 16},
158     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  32},
159     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  16},
160     /* 8bpp */
161     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0,  32},
162     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0,  16},
163     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 8, 0, 32, 8,  8,  8,  8,  32},
164     {SB_FLAGS,         PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 8, 0, 32, 8,  8,  8,  8,  16},
165     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 8,  3, 0,  3, 3, 2, 6, 0, 0, 0,  0,  0,  0,  0,  32},
166     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 8,  3, 0,  3, 3, 2, 6, 0, 0, 0,  0,  0,  0,  0,  16},
167     /* 4bpp */
168     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 0, 0, 16, 5,  6,  5,  0,  32},
169     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 0, 0, 16, 5,  6,  5,  0,  16},
170     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 8, 0, 16, 4,  4,  4,  4,  32},
171     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 8, 0, 16, 4,  4,  4,  4,  16},
172     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 4,  1, 0,  1, 1, 1, 2, 0, 0, 0,  0,  0,  0,  0,  32},
173     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 4,  1, 0,  1, 1, 1, 2, 0, 0, 0,  0,  0,  0,  0,  16},
174 };
175 
176 static const struct pixel_format pixel_formats_8[] =
177 {
178     /* 8bpp */
179     {SB_FLAGS_PALETTE, PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0,  32},
180     {SB_FLAGS_PALETTE, PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0,  16},
181     {DB_FLAGS_PALETTE, PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0,  32},
182     {DB_FLAGS_PALETTE, PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 0, 0, 32, 11, 11, 10, 0,  16},
183     {SB_FLAGS_PALETTE, PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 8, 0, 32, 8,  8,  8,  8,  32},
184     {SB_FLAGS_PALETTE, PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 8, 0, 32, 8,  8,  8,  8,  16},
185     {DB_FLAGS_PALETTE, PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 8, 0, 32, 8,  8,  8,  8,  32},
186     {DB_FLAGS_PALETTE, PFD_TYPE_RGBA,       8,  3, 0,  3, 3, 2, 6, 8, 0, 32, 8,  8,  8,  8,  16},
187     {SB_FLAGS_WINDOW,  PFD_TYPE_COLORINDEX, 8,  3, 0,  3, 3, 2, 6, 0, 0, 0,  0,  0,  0,  0,  32},
188     {SB_FLAGS_WINDOW,  PFD_TYPE_COLORINDEX, 8,  3, 0,  3, 3, 2, 6, 0, 0, 0,  0,  0,  0,  0,  16},
189     {DB_FLAGS,         PFD_TYPE_COLORINDEX, 8,  3, 0,  3, 3, 2, 6, 0, 0, 0,  0,  0,  0,  0,  32},
190     {DB_FLAGS,         PFD_TYPE_COLORINDEX, 8,  3, 0,  3, 3, 2, 6, 0, 0, 0,  0,  0,  0,  0,  16},
191     /* 24bpp */
192     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  32},
193     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  16},
194     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 32},
195     {SB_FLAGS,         PFD_TYPE_RGBA,       24, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 16},
196     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  32},
197     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 24, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  16},
198     /* 32bpp */
199     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  32},
200     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 0, 0, 64, 16, 16, 16, 0,  16},
201     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 32},
202     {SB_FLAGS,         PFD_TYPE_RGBA,       32, 8, 16, 8, 8, 8, 0, 8, 0, 64, 16, 16, 16, 16, 16},
203     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  32},
204     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 32, 8, 16, 8, 8, 8, 0, 0, 0, 0,  0,  0,  0,  0,  16},
205     /* 16 bpp */
206     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0,  32},
207     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 0, 0, 32, 11, 11, 10, 0,  16},
208     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 8, 0, 32, 8,  8,  8,  8,  32},
209     {SB_FLAGS,         PFD_TYPE_RGBA,       16, 5, 10, 5, 5, 5, 0, 8, 0, 32, 8,  8,  8,  8,  16},
210     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 16, 5, 10, 5, 5, 5, 0, 0, 0, 0,  0,  0,  0,  0,  32},
211     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 16, 5, 10, 5, 5, 5, 0, 0, 0, 0,  0,  0,  0,  0,  16},
212     /* 4bpp */
213     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 0, 0, 16, 5,  6,  5,  0,  32},
214     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 0, 0, 16, 5,  6,  5,  0,  16},
215     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 8, 0, 16, 4,  4,  4,  4,  32},
216     {SB_FLAGS,         PFD_TYPE_RGBA,       4,  1, 0,  1, 1, 1, 2, 8, 0, 16, 4,  4,  4,  4,  16},
217     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 4,  1, 0,  1, 1, 1, 2, 0, 0, 0,  0,  0,  0,  0,  32},
218     {SB_FLAGS,         PFD_TYPE_COLORINDEX, 4,  1, 0,  1, 1, 1, 2, 0, 0, 0,  0,  0,  0,  0,  16},
219 };
220 
221 struct sw_framebuffer
222 {
223     GLvisual *gl_visual;        /* Describes the buffers */
224     GLframebuffer *gl_buffer;   /* Depth, stencil, accum, etc buffers */
225 
226     const struct pixel_format* pixel_format;
227     HDC Hdc;
228 
229     /* Current width/height */
230     GLuint width; GLuint height;
231 
232     /* BackBuffer, if any */
233     BYTE* BackBuffer;
234 };
235 
236 struct sw_context
237 {
238     GLcontext *gl_ctx;          /* The core GL/Mesa context */
239 
240     /* This is to keep track of the size of the front buffer */
241     HHOOK hook;
242 
243     /* Our frame buffer*/
244     struct sw_framebuffer* fb;
245 
246     /* State variables */
247     union
248     {
249         struct
250         {
251             BYTE ClearColor;
252             BYTE CurrentColor;
253         } u8;
254         struct
255         {
256             USHORT ClearColor;
257             USHORT CurrentColor;
258         } u16;
259         struct
260         {
261             ULONG ClearColor;
262             ULONG CurrentColor;
263         } u24;
264         struct
265         {
266             ULONG ClearColor;
267             ULONG CurrentColor;
268         } u32;
269     };
270     GLenum Mode;
271 };
272 
273 /* WGL <-> mesa glue */
274 static const struct pixel_format* get_format(INT pf_index, INT* pf_count)
275 {
276     HDC hdc;
277     INT bpp, nb_format;
278     const struct pixel_format* ret;
279 
280     hdc = GetDC(NULL);
281     bpp = GetDeviceCaps(hdc, BITSPIXEL);
282     ReleaseDC(NULL, hdc);
283 
284     switch (bpp)
285     {
286 #define HANDLE_BPP(__x__)                               \
287     case __x__:                                         \
288         nb_format = ARRAYSIZE(pixel_formats_##__x__);   \
289         if ((pf_index > nb_format) || (pf_index <= 0))  \
290             ret = NULL;                                 \
291         else                                            \
292             ret = &pixel_formats_##__x__[pf_index - 1]; \
293     break
294 
295     HANDLE_BPP(32);
296     HANDLE_BPP(24);
297     HANDLE_BPP(16);
298     HANDLE_BPP(8);
299 #undef HANDLE_BPP
300     default:
301         FIXME("Unhandled bit depth %u, defaulting to 32bpp\n", bpp);
302         nb_format = ARRAYSIZE(pixel_formats_32);
303         if ((pf_index > nb_format) || (pf_index == 0))
304             ret = NULL;
305         else
306             ret = &pixel_formats_32[pf_index - 1];
307     }
308 
309     if (pf_count)
310         *pf_count = nb_format;
311 
312     return ret;
313 }
314 
315 INT sw_DescribePixelFormat(HDC hdc, INT format, UINT size, PIXELFORMATDESCRIPTOR* descr)
316 {
317     INT ret;
318     const struct pixel_format *pixel_format;
319 
320     TRACE("Describing format %i.\n", format);
321 
322     pixel_format = get_format(format, &ret);
323     if(!descr)
324         return ret;
325     if((format > ret) || (size != sizeof(*descr)))
326         return 0;
327 
328     /* Fill the structure */
329     descr->nSize            = sizeof(*descr);
330     descr->nVersion         = 1;
331     descr->dwFlags          = pixel_format->dwFlags;
332     descr->iPixelType       = pixel_format->iPixelType;
333     descr->cColorBits       = pixel_format->cColorBits;
334     descr->cRedBits         = pixel_format->cRedBits;
335     descr->cRedShift        = pixel_format->cRedShift;
336     descr->cGreenBits       = pixel_format->cGreenBits;
337     descr->cGreenShift      = pixel_format->cGreenShift;
338     descr->cBlueBits        = pixel_format->cBlueBits;
339     descr->cBlueShift       = pixel_format->cBlueShift;
340     descr->cAlphaBits       = pixel_format->cAlphaBits;
341     descr->cAlphaShift      = pixel_format->cAlphaShift;
342     descr->cAccumBits       = pixel_format->cAccumBits;
343     descr->cAccumRedBits    = pixel_format->cAccumRedBits;
344     descr->cAccumGreenBits  = pixel_format->cAccumGreenBits;
345     descr->cAccumBlueBits   = pixel_format->cAccumBlueBits;
346     descr->cAccumAlphaBits  = pixel_format->cAccumAlphaBits;
347     descr->cDepthBits       = pixel_format->cDepthBits;
348     descr->cStencilBits     = STENCIL_BITS;
349     descr->cAuxBuffers      = 0;
350     descr->iLayerType       = PFD_MAIN_PLANE;
351     descr->bReserved        = 0;
352     descr->dwLayerMask      = 0;
353     descr->dwVisibleMask    = 0;
354     descr->dwDamageMask     = 0;
355 
356     return ret;
357 }
358 
359 BOOL sw_SetPixelFormat(HDC hdc, struct wgl_dc_data* dc_data, INT format)
360 {
361     struct sw_framebuffer* fb;
362     const struct pixel_format *pixel_format;
363 
364     /* So, someone is crazy enough to ask for sw implementation. Announce it. */
365     TRACE("OpenGL software implementation START for hdc %p, format %i!\n", hdc, format);
366 
367     pixel_format = get_format(format, NULL);
368     if (!pixel_format)
369         return FALSE;
370 
371     /* allocate our structure */
372     fb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*fb));
373     if(!fb)
374     {
375         ERR("HeapAlloc FAILED!\n");
376         return FALSE;
377     }
378     /* Set the format */
379     fb->pixel_format = pixel_format;
380 
381     fb->gl_visual = gl_create_visual(
382             pixel_format->iPixelType == PFD_TYPE_RGBA,
383             pixel_format->cAlphaBits != 0,
384             (pixel_format->dwFlags & PFD_DOUBLEBUFFER) != 0,
385             pixel_format->cDepthBits,
386             STENCIL_BITS,
387             max(max(max(pixel_format->cAccumRedBits, pixel_format->cAccumGreenBits), pixel_format->cAccumBlueBits), pixel_format->cAccumAlphaBits),
388             pixel_format->iPixelType == PFD_TYPE_COLORINDEX ? pixel_format->cColorBits : 0,
389             ((1ul << pixel_format->cRedBits) - 1),
390             ((1ul << pixel_format->cGreenBits) - 1),
391             ((1ul << pixel_format->cBlueBits) - 1),
392             pixel_format->cAlphaBits != 0 ? ((1ul << pixel_format->cAlphaBits) - 1) : 255.0f,
393             pixel_format->cRedBits,
394             pixel_format->cGreenBits,
395             pixel_format->cBlueBits,
396             pixel_format->cAlphaBits);
397 
398     if(!fb->gl_visual)
399     {
400         ERR("Failed to allocate a GL visual.\n");
401         HeapFree(GetProcessHeap(), 0, fb);
402         return FALSE;
403     }
404 
405     /* Allocate the framebuffer structure */
406     fb->gl_buffer = gl_create_framebuffer(fb->gl_visual);
407     if (!fb->gl_buffer) {
408         ERR("Failed to allocate the mesa framebuffer structure.\n");
409         gl_destroy_visual( fb->gl_visual );
410         HeapFree(GetProcessHeap(), 0, fb);
411         return FALSE;
412     }
413 
414     /* Save our DC */
415     fb->Hdc = hdc;
416 
417     /* Everything went fine */
418     dc_data->sw_data = fb;
419     return TRUE;
420 }
421 
422 DHGLRC sw_CreateContext(struct wgl_dc_data* dc_data)
423 {
424     struct sw_context* sw_ctx;
425     struct sw_framebuffer* fb = dc_data->sw_data;
426 
427     sw_ctx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sw_ctx));
428     if(!sw_ctx)
429         return NULL;
430 
431     /* Initialize the context */
432     sw_ctx->gl_ctx = gl_create_context(fb->gl_visual, NULL, sw_ctx);
433     if(!sw_ctx->gl_ctx)
434     {
435         ERR("Failed to initialize the mesa context.\n");
436         HeapFree(GetProcessHeap(), 0, sw_ctx);
437         return NULL;
438     }
439 
440     sw_ctx->fb = fb;
441 
442     /* Choose relevant default */
443     sw_ctx->Mode = fb->gl_visual->DBflag ? GL_BACK : GL_FRONT;
444 
445     return (DHGLRC)sw_ctx;
446 }
447 
448 BOOL sw_DeleteContext(DHGLRC dhglrc)
449 {
450     struct sw_context* sw_ctx = (struct sw_context*)dhglrc;
451     /* Those get clobbered by _mesa_free_context_data via _glapi_set{context,dispath_table} */
452     void* icd_save = IntGetCurrentICDPrivate();
453     const GLDISPATCHTABLE* table_save = IntGetCurrentDispatchTable();
454 
455     /* Destroy everything */
456     gl_destroy_context(sw_ctx->gl_ctx);
457 
458     HeapFree(GetProcessHeap(), 0, sw_ctx);
459 
460     /* Restore this */
461     IntSetCurrentDispatchTable(table_save);
462     IntSetCurrentICDPrivate(icd_save);
463 
464     return TRUE;
465 }
466 
467 extern void APIENTRY _mesa_ColorTableEXT(GLenum, GLenum, GLsizei, GLenum, GLenum, const void*);
468 extern void APIENTRY _mesa_ColorSubTableEXT(GLenum, GLsizei, GLsizei, GLenum, GLenum, const void*);
469 extern void APIENTRY _mesa_GetColorTableEXT(GLenum, GLenum, GLenum, void*);
470 extern void APIENTRY _mesa_GetColorTableParameterivEXT(GLenum, GLenum, GLfloat*);
471 extern void APIENTRY _mesa_GetColorTableParameterfvEXT(GLenum, GLenum, GLint*);
472 
473 static void APIENTRY _swimpl_AddSwapHintRectWIN(GLint x, GLint y, GLsizei width, GLsizei height)
474 {
475     UNIMPLEMENTED;
476 }
477 
478 PROC sw_GetProcAddress(LPCSTR name)
479 {
480     /* GL_EXT_paletted_texture */
481     if (strcmp(name, "glColorTableEXT") == 0)
482         return (PROC)_mesa_ColorTableEXT;
483     if (strcmp(name, "glColorSubTableEXT") == 0)
484         return (PROC)_mesa_ColorSubTableEXT;
485     if (strcmp(name, "glColorGetTableEXT") == 0)
486         return (PROC)_mesa_GetColorTableEXT;
487     if (strcmp(name, "glGetColorTableParameterivEXT") == 0)
488         return (PROC)_mesa_GetColorTableParameterivEXT;
489     if (strcmp(name, "glGetColorTableParameterfvEXT") == 0)
490         return (PROC)_mesa_GetColorTableParameterfvEXT;
491     if (strcmp(name, "glAddSwapHintRectWIN") == 0)
492         return (PROC)_swimpl_AddSwapHintRectWIN;
493 
494     WARN("Asking for proc address %s, returning NULL.\n", name);
495     return NULL;
496 }
497 
498 BOOL sw_CopyContext(DHGLRC dhglrcSrc, DHGLRC dhglrcDst, UINT mask)
499 {
500     FIXME("Software wglCopyContext is UNIMPLEMENTED, mask %lx.\n", mask);
501     return FALSE;
502 }
503 
504 BOOL sw_ShareLists(DHGLRC dhglrcSrc, DHGLRC dhglrcDst)
505 {
506 #if 0
507     struct sw_context* sw_ctx_src = (struct sw_context*)dhglrcSrc;
508     struct sw_context* sw_ctx_dst = (struct sw_context*)dhglrcDst;
509 
510     /* See if it was already shared */
511     if(sw_ctx_dst->gl_ctx->Shared->RefCount > 1)
512         return FALSE;
513 
514     /* Unreference the old, share the new */
515     gl_reference_shared_state(sw_ctx_dst->gl_ctx,
516         &sw_ctx_dst->gl_ctx->Shared,
517         sw_ctx_src->gl_ctx->Shared);
518 #endif
519     FIXME("Unimplemented!\n");
520     return TRUE;
521 }
522 
523 static
524 LRESULT CALLBACK
525 sw_call_window_proc(
526    int nCode,
527    WPARAM wParam,
528    LPARAM lParam )
529 {
530     struct wgl_dc_data* dc_data = IntGetCurrentDcData();
531     struct sw_context* ctx = (struct sw_context*)IntGetCurrentDHGLRC();
532     PCWPSTRUCT pParams = (PCWPSTRUCT)lParam;
533 
534     if((!dc_data) || (!ctx))
535         return 0;
536 
537     if(!(dc_data->flags & WGL_DC_OBJ_DC))
538         return 0;
539 
540     if((nCode < 0) || (dc_data->owner.hwnd != pParams->hwnd) || (dc_data->sw_data == NULL))
541         return CallNextHookEx(ctx->hook, nCode, wParam, lParam);
542 
543     if (pParams->message == WM_WINDOWPOSCHANGED)
544     {
545         /* We handle WM_WINDOWPOSCHANGED instead of WM_SIZE because according to
546          * http://blogs.msdn.com/oldnewthing/archive/2008/01/15/7113860.aspx
547          * WM_SIZE is generated from WM_WINDOWPOSCHANGED by DefWindowProc so it
548          * can be masked out by the application. */
549         LPWINDOWPOS lpWindowPos = (LPWINDOWPOS)pParams->lParam;
550         if((lpWindowPos->flags & SWP_SHOWWINDOW) ||
551             !(lpWindowPos->flags & SWP_NOMOVE) ||
552             !(lpWindowPos->flags & SWP_NOSIZE))
553         {
554             /* Size in WINDOWPOS includes the window frame, so get the size
555              * of the client area via GetClientRect.  */
556             RECT client_rect;
557             UINT width, height;
558 
559             TRACE("Got WM_WINDOWPOSCHANGED\n");
560 
561             GetClientRect(pParams->hwnd, &client_rect);
562             width = client_rect.right - client_rect.left;
563             height = client_rect.bottom - client_rect.top;
564             /* Do not reallocate for minimized windows */
565             if(width <= 0 || height <= 0)
566                 goto end;
567             /* Propagate to mesa */
568             gl_ResizeBuffersMESA(ctx->gl_ctx);
569         }
570     }
571 
572 end:
573     return CallNextHookEx(ctx->hook, nCode, wParam, lParam);
574 }
575 
576 static const char* renderer_string(void)
577 {
578     return "ReactOS SW Implementation";
579 }
580 
581 static inline void PUT_PIXEL_8(BYTE* Buffer, BYTE Value)
582 {
583     *Buffer = Value;
584 }
585 static inline void PUT_PIXEL_16(USHORT* Buffer, USHORT Value)
586 {
587     *Buffer = Value;
588 }
589 static inline void PUT_PIXEL_24(ULONG* Buffer, ULONG Value)
590 {
591     *Buffer &= 0xFF000000ul;
592     *Buffer |= Value & 0x00FFFFFF;
593 }
594 static inline void PUT_PIXEL_32(ULONG* Buffer, ULONG Value)
595 {
596     *Buffer = Value;
597 }
598 
599 static inline BYTE GET_PIXEL_8(BYTE* Buffer)
600 {
601     return *Buffer;
602 }
603 
604 static inline USHORT GET_PIXEL_16(USHORT* Buffer)
605 {
606     return *Buffer;
607 }
608 
609 static inline ULONG GET_PIXEL_24(ULONG* Buffer)
610 {
611     return *Buffer & 0x00FFFFFF;
612 }
613 
614 static inline ULONG GET_PIXEL_32(ULONG* Buffer)
615 {
616     return *Buffer;
617 }
618 
619 static inline COLORREF MAKE_COLORREF_8(const struct pixel_format *format, BYTE Color)
620 {
621     BYTE R,G,B;
622 
623     if (format->iPixelType == PFD_TYPE_COLORINDEX)
624         return PALETTEINDEX(Color);
625 
626     R = (Color & 0x7) << 5;
627     G = (Color & 0x38) << 2;
628     B = Color & 0xC;
629 
630     return RGB(R, G, B);
631 }
632 
633 static inline COLORREF MAKE_COLORREF_16(const struct pixel_format *format, USHORT Color)
634 {
635     BYTE R,G,B;
636 
637     if (format->iPixelType == PFD_TYPE_COLORINDEX)
638         return PALETTEINDEX(Color);
639 
640     R = (Color & 0x7) << 5;
641     G = (Color & 0x38) << 2;
642     B = Color & 0xC;
643 
644     return RGB(R, G, B);
645 }
646 
647 static inline COLORREF MAKE_COLORREF_24(const struct pixel_format *format, ULONG Color)
648 {
649     BYTE R,G,B;
650 
651     if (format->iPixelType == PFD_TYPE_COLORINDEX)
652         return PALETTEINDEX(Color);
653 
654     R = (Color & 0xFF0000) >> 16;
655     G = (Color & 0x00FF00) >> 8;
656     B = Color & 0xFF;
657 
658     return RGB(R, G, B);
659 }
660 
661 static inline COLORREF MAKE_COLORREF_32(const struct pixel_format *format, ULONG Color)
662 {
663     BYTE R,G,B;
664 
665     if (format->iPixelType == PFD_TYPE_COLORINDEX)
666         return PALETTEINDEX(Color);
667 
668     R = (Color & 0xFF0000) >> 16;
669     G = (Color & 0x00FF00) >> 8;
670     B = Color & 0xFF;
671 
672     return RGB(R, G, B);
673 }
674 
675 
676 static inline BYTE PACK_COLOR_8(GLubyte r, GLubyte g, GLubyte b)
677 {
678     return (r & 0x7) | ((g & 0x7) << 3) | ((b & 0x3) << 6);
679 }
680 
681 static inline USHORT PACK_COLOR_16(GLubyte r, GLubyte g, GLubyte b)
682 {
683     return ((r & 0x1F) << 11) | ((g & 0x3F) << 5) | (b & 0x1F);
684 }
685 
686 static inline ULONG PACK_COLOR_24(GLubyte r, GLubyte g, GLubyte b)
687 {
688     return (r << 16) | (g << 8) | (b);
689 }
690 
691 static inline ULONG PACK_COLOR_32(GLubyte r, GLubyte g, GLubyte b)
692 {
693     return (r << 16) | (g << 8) | (b);
694 }
695 
696 static inline COLORREF PACK_COLORREF_8(GLubyte r, GLubyte g, GLubyte b)
697 {
698     return RGB(r << 5, g << 5, b << 6);
699 }
700 
701 static inline COLORREF PACK_COLORREF_16(GLubyte r, GLubyte g, GLubyte b)
702 {
703     return RGB(r << 3, g << 2, b << 3);
704 }
705 
706 static inline COLORREF PACK_COLORREF_24(GLubyte r, GLubyte g, GLubyte b)
707 {
708     return RGB(r, g, b);
709 }
710 
711 static inline COLORREF PACK_COLORREF_32(GLubyte r, GLubyte g, GLubyte b)
712 {
713     return RGB(r, g, b);
714 }
715 
716 static inline void UNPACK_COLOR_8(BYTE Color, GLubyte* r, GLubyte* g, GLubyte* b)
717 {
718     *r = Color & 0x7;
719     *g = (Color >> 3) & 0x7;
720     *b = (Color >> 6) & 0x3;
721 }
722 
723 static inline void UNPACK_COLOR_16(USHORT Color, GLubyte* r, GLubyte* g, GLubyte* b)
724 {
725     *r = (Color >> 11) & 0x1F;
726     *g = (Color >> 5) & 0x3F;
727     *b = Color & 0x1F;
728 }
729 
730 static inline void UNPACK_COLOR_24(ULONG Color, GLubyte* r, GLubyte* g, GLubyte* b)
731 {
732     *r = (Color >> 16) & 0xFF;
733     *g = (Color >> 8) & 0xFF;
734     *b = Color & 0xFF;
735 }
736 
737 static inline void UNPACK_COLOR_32(ULONG Color, GLubyte* r, GLubyte* g, GLubyte* b)
738 {
739     *r = (Color >> 16) & 0xFF;
740     *g = (Color >> 8) & 0xFF;
741     *b = Color & 0xFF;
742 }
743 
744 static inline void UNPACK_COLORREF_8(COLORREF Color, GLubyte* r, GLubyte* g, GLubyte* b)
745 {
746     *r = GetRValue(Color) >> 5;
747     *g = GetGValue(Color) >> 5;
748     *b = GetBValue(Color) >> 6;
749 }
750 
751 static inline void UNPACK_COLORREF_16(COLORREF Color, GLubyte* r, GLubyte* g, GLubyte* b)
752 {
753     *r = GetRValue(Color) >> 3;
754     *g = GetGValue(Color) >> 2;
755     *b = GetBValue(Color) >> 3;
756 }
757 
758 static inline void UNPACK_COLORREF_24(COLORREF Color, GLubyte* r, GLubyte* g, GLubyte* b)
759 {
760     *r = GetRValue(Color);
761     *g = GetGValue(Color);
762     *b = GetBValue(Color);
763 }
764 
765 static inline void UNPACK_COLORREF_32(COLORREF Color, GLubyte* r, GLubyte* g, GLubyte* b)
766 {
767     *r = GetRValue(Color);
768     *g = GetGValue(Color);
769     *b = GetBValue(Color);
770 }
771 
772 /*
773 * Set the color index used to clear the color buffer.
774 */
775 #define CLEAR_INDEX(__bpp, __type)                              \
776 static void clear_index_##__bpp(GLcontext* ctx, GLuint index)   \
777 {                                                               \
778     struct sw_context* sw_ctx = ctx->DriverCtx;                 \
779                                                                 \
780     sw_ctx->u##__bpp.ClearColor = (__type)index;                \
781 }
782 CLEAR_INDEX(8, BYTE)
783 CLEAR_INDEX(16, USHORT)
784 CLEAR_INDEX(24, ULONG)
785 CLEAR_INDEX(32, ULONG)
786 #undef CLEAR_INDEX
787 
788 /*
789 * Set the color used to clear the color buffer.
790 */
791 #define CLEAR_COLOR(__bpp)                                                                 \
792 static void clear_color_##__bpp( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )   \
793 {                                                                                               \
794     struct sw_context* sw_ctx = ctx->DriverCtx;                                                 \
795                                                                                                 \
796     sw_ctx->u##__bpp.ClearColor = PACK_COLOR_##__bpp(r, g, b);                                  \
797                                                                                                 \
798     TRACE("Set Clear color %u, %u, %u.\n", r, g, b);                                            \
799 }
800 CLEAR_COLOR(8)
801 CLEAR_COLOR(16)
802 CLEAR_COLOR(24)
803 CLEAR_COLOR(32)
804 #undef CLEAR_COLOR
805 
806 /*
807  * Clear the specified region of the color buffer using the clear color
808  * or index as specified by one of the two functions above.
809  */
810 static void clear_frontbuffer(
811     struct sw_context* sw_ctx,
812     struct sw_framebuffer* fb,
813     GLint x,
814     GLint y,
815     GLint width,
816     GLint height,
817     COLORREF ClearColor)
818 {
819     HBRUSH Brush;
820     BOOL ret;
821 
822     TRACE("Clearing front buffer (%u, %u, %u, %u), color 0x%08x.\n", x, y, width, height, ClearColor);
823 
824     Brush = CreateSolidBrush(ClearColor);
825     Brush = SelectObject(fb->Hdc, Brush);
826 
827     ret = PatBlt(fb->Hdc, x, fb->height - (y + height), width, height, PATCOPY);
828     if (!ret)
829     {
830         ERR("PatBlt failed. last Error %d.\n", GetLastError());
831     }
832 
833     Brush = SelectObject(fb->Hdc, Brush);
834     DeleteObject(Brush);
835 }
836 
837 #define CLEAR(__bpp, __type, __pixel_size)                                                          \
838 static void clear_##__bpp(GLcontext* ctx, GLboolean all,GLint x, GLint y, GLint width, GLint height)\
839 {                                                                                                   \
840     struct sw_context* sw_ctx = ctx->DriverCtx;                                                     \
841     struct sw_framebuffer* fb = sw_ctx->fb;                                                         \
842     BYTE* ScanLine;                                                                                 \
843                                                                                                     \
844     if (all)                                                                                        \
845     {                                                                                               \
846         x = y = 0;                                                                                  \
847         width = fb->width;                                                                          \
848         height = fb->height;                                                                        \
849     }                                                                                               \
850                                                                                                     \
851     if (sw_ctx->Mode == GL_FRONT)                                                                   \
852     {                                                                                               \
853         clear_frontbuffer(sw_ctx, fb, x, y, width, height,                                          \
854                 MAKE_COLORREF_##__bpp(fb->pixel_format, sw_ctx->u##__bpp.ClearColor));              \
855         return;                                                                                     \
856     }                                                                                               \
857                                                                                                     \
858     ScanLine = fb->BackBuffer + y * WIDTH_BYTES_ALIGN32(fb->width, __bpp);                          \
859     while (height--)                                                                                \
860     {                                                                                               \
861         BYTE* Buffer = ScanLine + x * __pixel_size;                                                 \
862         UINT n = width;                                                                             \
863                                                                                                     \
864         while (n--)                                                                                 \
865         {                                                                                           \
866             PUT_PIXEL_##__bpp((__type*)Buffer, sw_ctx->u##__bpp.ClearColor);                        \
867             Buffer += __pixel_size;                                                                 \
868         }                                                                                           \
869                                                                                                     \
870         ScanLine += WIDTH_BYTES_ALIGN32(fb->width, __bpp);                                          \
871     }                                                                                               \
872 }
873 CLEAR(8, BYTE, 1)
874 CLEAR(16, USHORT, 2)
875 CLEAR(24, ULONG, 3)
876 CLEAR(32, ULONG, 4)
877 #undef CLEAR
878 
879 /* Set the current color index. */
880 #define SET_INDEX(__bpp)                                        \
881 static void set_index_##__bpp(GLcontext* ctx, GLuint index)     \
882 {                                                               \
883     struct sw_context* sw_ctx = ctx->DriverCtx;                 \
884                                                                 \
885     sw_ctx->u##__bpp.CurrentColor = index;                      \
886 }
887 SET_INDEX(8)
888 SET_INDEX(16)
889 SET_INDEX(24)
890 SET_INDEX(32)
891 #undef SET_INDEX
892 
893 /* Set the current RGBA color. */
894 #define SET_COLOR(__bpp)                                                                    \
895 static void set_color_##__bpp( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a ) \
896 {                                                                                           \
897     struct sw_context* sw_ctx = ctx->DriverCtx;                                             \
898                                                                                             \
899     sw_ctx->u##__bpp.CurrentColor = PACK_COLOR_##__bpp(r, g, b);                            \
900 }
901 SET_COLOR(8)
902 SET_COLOR(16)
903 SET_COLOR(24)
904 SET_COLOR(32)
905 #undef SET_COLOR
906 
907 /*
908  * Selects either the front or back color buffer for reading and writing.
909  * mode is either GL_FRONT or GL_BACK.
910  */
911 static GLboolean set_buffer( GLcontext* ctx, GLenum mode )
912 {
913     struct sw_context* sw_ctx = ctx->DriverCtx;
914     struct sw_framebuffer* fb = sw_ctx->fb;
915 
916     if (!fb->gl_visual->DBflag)
917         return GL_FALSE;
918 
919     if ((mode != GL_FRONT) && (mode != GL_BACK))
920         return GL_FALSE;
921 
922     sw_ctx->Mode = mode;
923     return GL_TRUE;
924 }
925 
926 /* Return characteristics of the output buffer. */
927 static void buffer_size(GLcontext* ctx, GLuint *width, GLuint *height)
928 {
929     struct sw_context* sw_ctx = ctx->DriverCtx;
930     struct sw_framebuffer* fb = sw_ctx->fb;
931     HWND Window = WindowFromDC(fb->Hdc);
932 
933     if (Window)
934     {
935         RECT client_rect;
936         GetClientRect(Window, &client_rect);
937         *width = client_rect.right - client_rect.left;
938         *height = client_rect.bottom - client_rect.top;
939     }
940     else
941     {
942         /* We are drawing to a bitmap */
943         BITMAP bm;
944         HBITMAP Hbm;
945 
946         Hbm = GetCurrentObject(fb->Hdc, OBJ_BITMAP);
947 
948         if (!GetObjectW(Hbm, sizeof(bm), &bm))
949             return;
950 
951         TRACE("Framebuffer size : %i, %i\n", bm.bmWidth, bm.bmHeight);
952 
953         *width = bm.bmWidth;
954         *height = bm.bmHeight;
955     }
956 
957     if ((*width != fb->width) || (*height != fb->height))
958     {
959         const struct pixel_format* pixel_format = fb->pixel_format;
960 
961         if (pixel_format->dwFlags & PFD_DOUBLEBUFFER)
962         {
963             /* Allocate a new backbuffer */
964             size_t BufferSize = *height * WIDTH_BYTES_ALIGN32(*width, pixel_format->cColorBits);
965             if (!fb->BackBuffer)
966             {
967                 fb->BackBuffer = HeapAlloc(GetProcessHeap(), 0, BufferSize);
968             }
969             else
970             {
971                 fb->BackBuffer = HeapReAlloc(GetProcessHeap(), 0, fb->BackBuffer, BufferSize);
972             }
973             if (!fb->BackBuffer)
974             {
975                 ERR("Failed allocating back buffer !.\n");
976                 return;
977             }
978         }
979 
980         fb->width = *width;
981         fb->height = *height;
982     }
983 }
984 
985 /* Write a horizontal span of color pixels with a boolean mask. */
986 #define WRITE_COLOR_SPAN_FRONTBUFFER(__bpp)                                     \
987 static void write_color_span_frontbuffer_##__bpp(struct sw_framebuffer* fb,     \
988         GLuint n, GLint x, GLint y,                                             \
989         const GLubyte red[], const GLubyte green[],                             \
990         const GLubyte blue[], const GLubyte mask[] )                            \
991 {                                                                               \
992     TRACE("Writing color span at %u, %u (%u)\n", x, y, n);                      \
993                                                                                 \
994     if (mask)                                                                   \
995     {                                                                           \
996         while (n--)                                                             \
997         {                                                                       \
998             if (mask[n])                                                        \
999             {                                                                   \
1000                 SetPixel(fb->Hdc, x + n, fb->height - y,                        \
1001                         PACK_COLORREF_##__bpp(red[n], green[n], blue[n]));      \
1002             }                                                                   \
1003         }                                                                       \
1004     }                                                                           \
1005     else                                                                        \
1006     {                                                                           \
1007         while (n--)                                                             \
1008         {                                                                       \
1009             SetPixel(fb->Hdc, x + n, fb->height - y,                            \
1010                     PACK_COLORREF_##__bpp(red[n], green[n], blue[n]));          \
1011         }                                                                       \
1012     }                                                                           \
1013 }
1014 WRITE_COLOR_SPAN_FRONTBUFFER(8)
1015 WRITE_COLOR_SPAN_FRONTBUFFER(16)
1016 WRITE_COLOR_SPAN_FRONTBUFFER(24)
1017 WRITE_COLOR_SPAN_FRONTBUFFER(32)
1018 #undef WRITE_COLOR_SPAN_FRONTBUFFER
1019 
1020 #define WRITE_COLOR_SPAN(__bpp, __type, __pixel_size)                               \
1021 static void write_color_span_##__bpp(GLcontext* ctx,                                \
1022                                      GLuint n, GLint x, GLint y,                    \
1023                                      const GLubyte red[], const GLubyte green[],    \
1024                                      const GLubyte blue[], const GLubyte alpha[],   \
1025                                      const GLubyte mask[] )                         \
1026 {                                                                                   \
1027     struct sw_context* sw_ctx = ctx->DriverCtx;                                     \
1028     struct sw_framebuffer* fb = sw_ctx->fb;                                         \
1029     BYTE* Buffer;                                                                   \
1030                                                                                     \
1031     if (sw_ctx->Mode == GL_FRONT)                                                   \
1032     {                                                                               \
1033         write_color_span_frontbuffer_##__bpp(fb, n, x, y, red, green, blue, mask);  \
1034         return;                                                                     \
1035     }                                                                               \
1036                                                                                     \
1037     Buffer = fb->BackBuffer + y * WIDTH_BYTES_ALIGN32(fb->width, __bpp)             \
1038             + (x + n) * __pixel_size;                                               \
1039     if (mask)                                                                       \
1040     {                                                                               \
1041         while (n--)                                                                 \
1042         {                                                                           \
1043             Buffer -= __pixel_size;                                                 \
1044             if (mask[n])                                                            \
1045             {                                                                       \
1046                 PUT_PIXEL_##__bpp((__type*)Buffer,                                  \
1047                         PACK_COLOR_##__bpp(red[n], green[n], blue[n]));             \
1048             }                                                                       \
1049         }                                                                           \
1050     }                                                                               \
1051     else                                                                            \
1052     {                                                                               \
1053         while (n--)                                                                 \
1054         {                                                                           \
1055             Buffer -= __pixel_size;                                                 \
1056             PUT_PIXEL_##__bpp((__type*)Buffer,                                      \
1057                     PACK_COLOR_##__bpp(red[n], green[n], blue[n]));                 \
1058         }                                                                           \
1059     }                                                                               \
1060 }
1061 WRITE_COLOR_SPAN(8, BYTE, 1)
1062 WRITE_COLOR_SPAN(16, USHORT, 2)
1063 WRITE_COLOR_SPAN(24, ULONG, 3)
1064 WRITE_COLOR_SPAN(32, ULONG, 4)
1065 #undef WRITE_COLOR_SPAN
1066 
1067 static void write_monocolor_span_frontbuffer(struct sw_framebuffer* fb, GLuint n, GLint x, GLint y,
1068         const GLubyte mask[], COLORREF Color)
1069 {
1070     TRACE("Writing monocolor span at %u %u (%u), Color 0x%08x", x, y, n, Color);
1071 
1072     if (mask)
1073     {
1074         while (n--)
1075         {
1076             if (mask[n])
1077                 SetPixel(fb->Hdc, x + n, y, Color);
1078         }
1079     }
1080     else
1081     {
1082         HBRUSH Brush = CreateSolidBrush(Color);
1083         Brush = SelectObject(fb->Hdc, Brush);
1084 
1085         PatBlt(fb->Hdc, x, fb->height - y, n, 1, PATCOPY);
1086 
1087         Brush = SelectObject(fb->Hdc, Brush);
1088         DeleteObject(Brush);
1089     }
1090 }
1091 
1092 #define WRITE_MONOCOLOR_SPAN(__bpp, __type, __pixel_size)                                           \
1093 static void write_monocolor_span_##__bpp(GLcontext* ctx,                                            \
1094                                  GLuint n, GLint x, GLint y,                                        \
1095                                  const GLubyte mask[])                                              \
1096 {                                                                                                   \
1097     struct sw_context* sw_ctx = ctx->DriverCtx;                                                     \
1098     struct sw_framebuffer* fb = sw_ctx->fb;                                                         \
1099     BYTE* Buffer;                                                                                   \
1100                                                                                                     \
1101     if (sw_ctx->Mode == GL_FRONT)                                                                   \
1102     {                                                                                               \
1103         write_monocolor_span_frontbuffer(fb, n, x, y, mask,                                         \
1104                 MAKE_COLORREF_##__bpp(fb->pixel_format, sw_ctx->u##__bpp.CurrentColor));            \
1105         return;                                                                                     \
1106     }                                                                                               \
1107                                                                                                     \
1108     Buffer = fb->BackBuffer + y * WIDTH_BYTES_ALIGN32(fb->width, __bpp) + (x + n) * __pixel_size;   \
1109     if (mask)                                                                                       \
1110     {                                                                                               \
1111         while (n--)                                                                                 \
1112         {                                                                                           \
1113             Buffer -= __pixel_size;                                                                 \
1114             if (mask[n])                                                                            \
1115                 PUT_PIXEL_##__bpp((__type*)Buffer, sw_ctx->u##__bpp.CurrentColor);                  \
1116         }                                                                                           \
1117     }                                                                                               \
1118     else                                                                                            \
1119     {                                                                                               \
1120         while(n--)                                                                                  \
1121         {                                                                                           \
1122             Buffer -= __pixel_size;                                                                 \
1123             PUT_PIXEL_##__bpp((__type*)Buffer, sw_ctx->u##__bpp.CurrentColor);                      \
1124         }                                                                                           \
1125     }                                                                                               \
1126 }
1127 WRITE_MONOCOLOR_SPAN(8, BYTE, 1)
1128 WRITE_MONOCOLOR_SPAN(16, USHORT, 2)
1129 WRITE_MONOCOLOR_SPAN(24, ULONG, 3)
1130 WRITE_MONOCOLOR_SPAN(32, ULONG, 4)
1131 #undef WRITE_MONOCOLOR_SPAN
1132 
1133 /* Write an array of pixels with a boolean mask. */
1134 #define WRITE_COLOR_PIXELS(__bpp, __type, __pixel_size)                                             \
1135 static void write_color_pixels_##__bpp(GLcontext* ctx,                                              \
1136                                GLuint n, const GLint x[], const GLint y[],                          \
1137                                const GLubyte r[], const GLubyte g[],                                \
1138                                const GLubyte b[], const GLubyte a[],                                \
1139                                const GLubyte mask[])                                                \
1140 {                                                                                                   \
1141     struct sw_context* sw_ctx = ctx->DriverCtx;                                                     \
1142     struct sw_framebuffer* fb = sw_ctx->fb;                                                         \
1143                                                                                                     \
1144     TRACE("Writing color pixels\n");                                                                \
1145                                                                                                     \
1146     if (sw_ctx->Mode == GL_FRONT)                                                                   \
1147     {                                                                                               \
1148         while (n--)                                                                                 \
1149         {                                                                                           \
1150             if (mask[n])                                                                            \
1151             {                                                                                       \
1152                 TRACE("Setting pixel %u, %u to 0x%08x.\n", x[n], fb->height - y[n],                 \
1153                         PACK_COLORREF_##__bpp(r[n], g[n], b[n]));                                   \
1154                 SetPixel(fb->Hdc, x[n], fb->height - y[n],                                          \
1155                         PACK_COLORREF_##__bpp(r[n], g[n], b[n]));                                   \
1156             }                                                                                       \
1157         }                                                                                           \
1158                                                                                                     \
1159         return;                                                                                     \
1160     }                                                                                               \
1161                                                                                                     \
1162     while (n--)                                                                                     \
1163     {                                                                                               \
1164         if (mask[n])                                                                                \
1165         {                                                                                           \
1166             BYTE* Buffer = fb->BackBuffer + y[n] * WIDTH_BYTES_ALIGN32(fb->width, __bpp)            \
1167                             + x[n] * __pixel_size;                                                  \
1168             PUT_PIXEL_##__bpp((__type*)Buffer, PACK_COLOR_##__bpp(r[n], g[n], b[n]));               \
1169         }                                                                                           \
1170     }                                                                                               \
1171 }
1172 WRITE_COLOR_PIXELS(8, BYTE, 1)
1173 WRITE_COLOR_PIXELS(16, USHORT, 2)
1174 WRITE_COLOR_PIXELS(24, ULONG, 3)
1175 WRITE_COLOR_PIXELS(32, ULONG, 4)
1176 #undef WRITE_COLOR_PIXELS
1177 
1178 static void write_monocolor_pixels_frontbuffer(
1179         struct sw_framebuffer* fb, GLuint n,
1180         const GLint x[], const GLint y[],
1181         const GLubyte mask[], COLORREF Color)
1182 {
1183     TRACE("Writing monocolor pixels to front buffer.\n");
1184 
1185     while (n--)
1186     {
1187         if (mask[n])
1188         {
1189             SetPixel(fb->Hdc, x[n], fb->height - y[n], Color);
1190         }
1191     }
1192 }
1193 
1194 /*
1195 * Write an array of pixels with a boolean mask.  The current color
1196 * is used for all pixels.
1197 */
1198 #define WRITE_MONOCOLOR_PIXELS(__bpp, __type, __pixel_size)                                 \
1199 static void write_monocolor_pixels_##__bpp(GLcontext* ctx, GLuint n,                        \
1200                                    const GLint x[], const GLint y[],                        \
1201                                    const GLubyte mask[] )                                   \
1202 {                                                                                           \
1203     struct sw_context* sw_ctx = ctx->DriverCtx;                                             \
1204     struct sw_framebuffer* fb = sw_ctx->fb;                                                 \
1205                                                                                             \
1206     if (sw_ctx->Mode == GL_FRONT)                                                           \
1207     {                                                                                       \
1208         write_monocolor_pixels_frontbuffer(fb, n, x, y, mask,                               \
1209                 MAKE_COLORREF_##__bpp(fb->pixel_format, sw_ctx->u##__bpp.CurrentColor));    \
1210                                                                                             \
1211         return;                                                                             \
1212     }                                                                                       \
1213                                                                                             \
1214     while (n--)                                                                             \
1215     {                                                                                       \
1216         if (mask[n])                                                                        \
1217         {                                                                                   \
1218             BYTE* Buffer = fb->BackBuffer + y[n] * WIDTH_BYTES_ALIGN32(fb->width, 32)       \
1219                     + x[n] * __pixel_size;                                                  \
1220             PUT_PIXEL_##__bpp((__type*)Buffer, sw_ctx->u##__bpp.CurrentColor);              \
1221         }                                                                                   \
1222     }                                                                                       \
1223 }
1224 WRITE_MONOCOLOR_PIXELS(8, BYTE, 1)
1225 WRITE_MONOCOLOR_PIXELS(16, USHORT, 2)
1226 WRITE_MONOCOLOR_PIXELS(24, ULONG, 3)
1227 WRITE_MONOCOLOR_PIXELS(32, ULONG, 4)
1228 #undef WRITE_MONOCOLOR_PIXELS
1229 
1230 /* Write a horizontal span of color pixels with a boolean mask. */
1231 static void write_index_span( GLcontext* ctx,
1232                              GLuint n, GLint x, GLint y,
1233                              const GLuint index[],
1234                              const GLubyte mask[] )
1235 {
1236     ERR("Not implemented yet !\n");
1237 }
1238 
1239 /* Write an array of pixels with a boolean mask. */
1240 static void write_index_pixels( GLcontext* ctx,
1241                                GLuint n, const GLint x[], const GLint y[],
1242                                const GLuint index[], const GLubyte mask[] )
1243 {
1244     ERR("Not implemented yet !\n");
1245 }
1246 
1247 /* Read a horizontal span of color-index pixels. */
1248 static void read_index_span( GLcontext* ctx, GLuint n, GLint x, GLint y, GLuint index[])
1249 {
1250     ERR("Not implemented yet !\n");
1251 }
1252 
1253 /* Read a horizontal span of color pixels. */
1254 #define READ_COLOR_SPAN(__bpp, __type, __pixel_size)                            \
1255 static void read_color_span_##__bpp(GLcontext* ctx,                             \
1256                             GLuint n, GLint x, GLint y,                         \
1257                             GLubyte red[], GLubyte green[],                     \
1258                             GLubyte blue[], GLubyte alpha[] )                   \
1259 {                                                                               \
1260     struct sw_context* sw_ctx = ctx->DriverCtx;                                 \
1261     struct sw_framebuffer* fb = sw_ctx->fb;                                     \
1262     BYTE* Buffer;                                                               \
1263                                                                                 \
1264     if (sw_ctx->Mode == GL_FRONT)                                               \
1265     {                                                                           \
1266         COLORREF Color;                                                         \
1267         while (n--)                                                             \
1268         {                                                                       \
1269             Color = GetPixel(fb->Hdc, x + n, fb->height - y);                   \
1270             UNPACK_COLORREF_##__bpp(Color, &red[n], &green[n], &blue[n]);       \
1271             alpha[n] = 0;                                                       \
1272         }                                                                       \
1273                                                                                 \
1274         return;                                                                 \
1275     }                                                                           \
1276                                                                                 \
1277     Buffer = fb->BackBuffer + y * WIDTH_BYTES_ALIGN32(fb->width, __bpp)         \
1278             + (x + n) * __pixel_size;                                           \
1279     while (n--)                                                                 \
1280     {                                                                           \
1281         Buffer -= __pixel_size;                                                 \
1282         UNPACK_COLOR_##__bpp(GET_PIXEL_##__bpp((__type*)Buffer),                \
1283                 &blue[n], &green[n], &red[n]);                                  \
1284         alpha[n] = 0;                                                           \
1285     }                                                                           \
1286 }
1287 READ_COLOR_SPAN(8, BYTE, 1)
1288 READ_COLOR_SPAN(16, USHORT, 2)
1289 READ_COLOR_SPAN(24, ULONG, 3)
1290 READ_COLOR_SPAN(32, ULONG, 4)
1291 #undef READ_COLOR_SPAN
1292 
1293 /* Read an array of color index pixels. */
1294 static void read_index_pixels(GLcontext* ctx,
1295                               GLuint n, const GLint x[], const GLint y[],
1296                               GLuint index[], const GLubyte mask[])
1297 {
1298 
1299     ERR("Not implemented yet !\n");
1300 }
1301 
1302 /* Read an array of color pixels. */
1303 #define READ_COLOR_PIXELS(__bpp, __type, __pixel_size)                                      \
1304 static void read_color_pixels_##__bpp(GLcontext* ctx,                                       \
1305                               GLuint n, const GLint x[], const GLint y[],                   \
1306                               GLubyte red[], GLubyte green[],                               \
1307                               GLubyte blue[], GLubyte alpha[],                              \
1308                               const GLubyte mask[] )                                        \
1309 {                                                                                           \
1310     struct sw_context* sw_ctx = ctx->DriverCtx;                                             \
1311     struct sw_framebuffer* fb = sw_ctx->fb;                                                 \
1312                                                                                             \
1313     if (sw_ctx->Mode == GL_FRONT)                                                           \
1314     {                                                                                       \
1315         COLORREF Color;                                                                     \
1316         while (n--)                                                                         \
1317         {                                                                                   \
1318             if (mask[n])                                                                    \
1319             {                                                                               \
1320                 Color = GetPixel(fb->Hdc, x[n], fb->height - y[n]);                         \
1321                 UNPACK_COLORREF_##__bpp(Color, &red[n], &green[n], &blue[n]);               \
1322                 alpha[n] = 0;                                                               \
1323             }                                                                               \
1324         }                                                                                   \
1325                                                                                             \
1326         return;                                                                             \
1327     }                                                                                       \
1328                                                                                             \
1329     while (n--)                                                                             \
1330     {                                                                                       \
1331         if (mask[n])                                                                        \
1332         {                                                                                   \
1333             BYTE *Buffer = fb->BackBuffer + y[n] * WIDTH_BYTES_ALIGN32(fb->width, __bpp)    \
1334                     + x[n] * __pixel_size;                                                  \
1335             UNPACK_COLOR_##__bpp(GET_PIXEL_##__bpp((__type*)Buffer),                        \
1336                     &blue[n], &green[n], &red[n]);                                          \
1337             alpha[n] = 0;                                                                   \
1338         }                                                                                   \
1339     }                                                                                       \
1340 }
1341 READ_COLOR_PIXELS(8, BYTE, 1)
1342 READ_COLOR_PIXELS(16, USHORT, 2)
1343 READ_COLOR_PIXELS(24, ULONG, 3)
1344 READ_COLOR_PIXELS(32, ULONG, 4)
1345 #undef READ_COLOR_PIXELS
1346 
1347 static void setup_DD_pointers( GLcontext* ctx )
1348 {
1349     struct sw_context* sw_ctx = ctx->DriverCtx;
1350 
1351     ctx->Driver.RendererString = renderer_string;
1352     ctx->Driver.UpdateState = setup_DD_pointers;
1353 
1354     switch (sw_ctx->fb->pixel_format->cColorBits)
1355     {
1356 #define HANDLE_BPP(__bpp)                                                   \
1357     case __bpp:                                                             \
1358         ctx->Driver.ClearIndex = clear_index_##__bpp;                       \
1359         ctx->Driver.ClearColor = clear_color_##__bpp;                       \
1360         ctx->Driver.Clear = clear_##__bpp;                                  \
1361         ctx->Driver.Index = set_index_##__bpp;                              \
1362         ctx->Driver.Color = set_color_##__bpp;                              \
1363         ctx->Driver.WriteColorSpan       = write_color_span_##__bpp;        \
1364         ctx->Driver.WriteMonocolorSpan   = write_monocolor_span_##__bpp;    \
1365         ctx->Driver.WriteMonoindexSpan   = write_monocolor_span_##__bpp;    \
1366         ctx->Driver.WriteColorPixels     = write_color_pixels_##__bpp;      \
1367         ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels_##__bpp;  \
1368         ctx->Driver.WriteMonoindexPixels = write_monocolor_pixels_##__bpp;  \
1369         ctx->Driver.ReadColorSpan = read_color_span_##__bpp;                \
1370         ctx->Driver.ReadColorPixels = read_color_pixels_##__bpp;            \
1371         break
1372 HANDLE_BPP(8);
1373 HANDLE_BPP(16);
1374 HANDLE_BPP(24);
1375 HANDLE_BPP(32);
1376 #undef HANDLE_BPP
1377     default:
1378         ERR("Unhandled bit depth %u, defaulting to 32bpp.\n", sw_ctx->fb->pixel_format->cColorBits);
1379         ctx->Driver.ClearIndex = clear_index_32;
1380         ctx->Driver.ClearColor = clear_color_32;
1381         ctx->Driver.Clear = clear_32;
1382         ctx->Driver.Index = set_index_32;
1383         ctx->Driver.Color = set_color_32;
1384         ctx->Driver.WriteColorSpan       = write_color_span_32;
1385         ctx->Driver.WriteMonocolorSpan   = write_monocolor_span_32;
1386         ctx->Driver.WriteMonoindexSpan   = write_monocolor_span_32;
1387         ctx->Driver.WriteColorPixels     = write_color_pixels_32;
1388         ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels_32;
1389         ctx->Driver.WriteMonoindexPixels = write_monocolor_pixels_32;
1390         ctx->Driver.ReadColorSpan = read_color_span_32;
1391         ctx->Driver.ReadColorPixels = read_color_pixels_32;
1392         break;
1393     }
1394 
1395     ctx->Driver.SetBuffer = set_buffer;
1396     ctx->Driver.GetBufferSize = buffer_size;
1397 
1398     /* Pixel/span writing functions: */
1399     ctx->Driver.WriteIndexSpan       = write_index_span;
1400     ctx->Driver.WriteIndexPixels     = write_index_pixels;
1401 
1402     /* Pixel/span reading functions: */
1403     ctx->Driver.ReadIndexSpan = read_index_span;
1404     ctx->Driver.ReadIndexPixels = read_index_pixels;
1405 }
1406 
1407 /* Declare API table */
1408 #define USE_GL_FUNC(name, proto_args, call_args, offset, stack) extern void WINAPI _mesa_##name proto_args ;
1409 #define USE_GL_FUNC_RET(name, ret_type, proto_args, call_args, offset, stack) extern ret_type WINAPI _mesa_##name proto_args ;
1410 #include "glfuncs.h"
1411 
1412 static GLCLTPROCTABLE sw_api_table =
1413 {
1414     OPENGL_VERSION_110_ENTRIES,
1415     {
1416 #define USE_GL_FUNC(name, proto_args, call_args, offset, stack) _mesa_##name,
1417 #include "glfuncs.h"
1418     }
1419 };
1420 
1421 /* Glue code */
1422 GLcontext* gl_get_thread_context(void)
1423 {
1424     struct sw_context* sw_ctx = (struct sw_context*)IntGetCurrentDHGLRC();
1425     return sw_ctx->gl_ctx;
1426 }
1427 
1428 
1429 BOOL sw_SetContext(struct wgl_dc_data* dc_data, DHGLRC dhglrc)
1430 {
1431     struct sw_context* sw_ctx = (struct sw_context*)dhglrc;
1432     struct sw_framebuffer* fb = dc_data->sw_data;
1433     UINT width, height;
1434 
1435     /* Get framebuffer size */
1436     if(dc_data->flags & WGL_DC_OBJ_DC)
1437     {
1438         HWND hwnd = dc_data->owner.hwnd;
1439         RECT client_rect;
1440         if(!hwnd)
1441         {
1442             ERR("Physical DC without a window!\n");
1443             return FALSE;
1444         }
1445         if(!GetClientRect(hwnd, &client_rect))
1446         {
1447             ERR("GetClientRect failed!\n");
1448             return FALSE;
1449         }
1450 
1451         /* This is a physical DC. Setup the hook */
1452         sw_ctx->hook = SetWindowsHookEx(WH_CALLWNDPROC,
1453                             sw_call_window_proc,
1454                             NULL,
1455                             GetCurrentThreadId());
1456 
1457         /* Calculate width & height */
1458         width  = client_rect.right  - client_rect.left;
1459         height = client_rect.bottom - client_rect.top;
1460     }
1461     else /* OBJ_MEMDC */
1462     {
1463         BITMAP bm;
1464         HBITMAP hbmp;
1465         HDC hdc = dc_data->owner.hdc;
1466 
1467         if(fb->gl_visual->DBflag)
1468         {
1469             ERR("Memory DC called with a double buffered format.\n");
1470             return FALSE;
1471         }
1472 
1473         hbmp = GetCurrentObject( hdc, OBJ_BITMAP );
1474         if(!hbmp)
1475         {
1476             ERR("No Bitmap!\n");
1477             return FALSE;
1478         }
1479         if(GetObject(hbmp, sizeof(bm), &bm) == 0)
1480         {
1481             ERR("GetObject failed!\n");
1482             return FALSE;
1483         }
1484         width = bm.bmWidth;
1485         height = bm.bmHeight;
1486     }
1487 
1488     if(!width) width = 1;
1489     if(!height) height = 1;
1490 
1491     /* Also make the mesa context current to mesa */
1492     gl_make_current(sw_ctx->gl_ctx, fb->gl_buffer);
1493 
1494     /* Setup our functions */
1495     setup_DD_pointers(sw_ctx->gl_ctx);
1496 
1497     /* Set the viewport if this is the first time we initialize this context */
1498     if(sw_ctx->gl_ctx->Viewport.X == 0 &&
1499        sw_ctx->gl_ctx->Viewport.Y == 0 &&
1500        sw_ctx->gl_ctx->Viewport.Width == 0 &&
1501        sw_ctx->gl_ctx->Viewport.Height == 0)
1502     {
1503         gl_Viewport(sw_ctx->gl_ctx, 0, 0, width, height);
1504     }
1505 
1506     /* update the framebuffer size */
1507     gl_ResizeBuffersMESA(sw_ctx->gl_ctx);
1508 
1509     /* Use our API table */
1510     IntSetCurrentDispatchTable(&sw_api_table.glDispatchTable);
1511 
1512    /* We're good */
1513    return TRUE;
1514 }
1515 
1516 void sw_ReleaseContext(DHGLRC dhglrc)
1517 {
1518     struct sw_context* sw_ctx = (struct sw_context*)dhglrc;
1519 
1520     /* Forward to mesa */
1521     gl_make_current(NULL, NULL);
1522 
1523     /* Unhook */
1524     if(sw_ctx->hook)
1525     {
1526         UnhookWindowsHookEx(sw_ctx->hook);
1527         sw_ctx->hook = NULL;
1528     }
1529 }
1530 
1531 BOOL sw_SwapBuffers(HDC hdc, struct wgl_dc_data* dc_data)
1532 {
1533     struct sw_framebuffer* fb = dc_data->sw_data;
1534     char Buffer[sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD)];
1535     BITMAPINFO *bmi = (BITMAPINFO*)Buffer;
1536     BYTE Bpp = fb->pixel_format->cColorBits;
1537 
1538     if (!fb->gl_visual->DBflag)
1539         return TRUE;
1540 
1541     if (!fb->BackBuffer)
1542         return FALSE;
1543 
1544     bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
1545     bmi->bmiHeader.biBitCount = Bpp;
1546     bmi->bmiHeader.biClrImportant = 0;
1547     bmi->bmiHeader.biClrUsed = 0;
1548     bmi->bmiHeader.biPlanes = 1;
1549     bmi->bmiHeader.biSizeImage = WIDTH_BYTES_ALIGN32(fb->width, Bpp) * fb->height;
1550     bmi->bmiHeader.biXPelsPerMeter = 0;
1551     bmi->bmiHeader.biYPelsPerMeter = 0;
1552     bmi->bmiHeader.biHeight = fb->height;
1553     bmi->bmiHeader.biWidth = fb->width;
1554     bmi->bmiHeader.biCompression = Bpp == 16 ? BI_BITFIELDS : BI_RGB;
1555 
1556     if (Bpp == 16)
1557     {
1558         DWORD* BitMasks = (DWORD*)(&bmi->bmiColors[0]);
1559         BitMasks[0] = 0x0000F800;
1560         BitMasks[1] = 0x000007E0;
1561         BitMasks[2] = 0x0000001F;
1562     }
1563 
1564     return SetDIBitsToDevice(fb->Hdc, 0, 0, fb->width, fb->height, 0, 0, 0, fb->height, fb->BackBuffer, bmi,
1565             fb->pixel_format->iPixelType == PFD_TYPE_COLORINDEX ? DIB_PAL_COLORS : DIB_RGB_COLORS) != 0;
1566 }
1567