2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Renderbuffer adaptors.
28 * These fuctions are used to convert rendering from core Mesa's GLchan
29 * colors to 8 or 16-bit color channels in RGBA renderbuffers.
30 * This means Mesa can be compiled for 16 or 32-bit color processing
31 * and still render into 8 and 16-bit/channel renderbuffers.
38 #include "renderbuffer.h"
39 #include "rbadaptors.h"
43 Delete_wrapper(struct gl_renderbuffer
*rb
)
45 /* Decrement reference count on the buffer we're wrapping and delete
46 * it if refcount hits zero.
48 _mesa_reference_renderbuffer(&rb
->Wrapped
, NULL
);
51 _mesa_delete_renderbuffer(rb
);
56 AllocStorage_wrapper(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
57 GLenum internalFormat
, GLuint width
, GLuint height
)
59 GLboolean b
= rb
->Wrapped
->AllocStorage(ctx
, rb
->Wrapped
, internalFormat
,
70 GetPointer_wrapper(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
82 GetRow_16wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
83 GLint x
, GLint y
, void *values
)
85 GLubyte values8
[MAX_WIDTH
* 4];
86 GLushort
*values16
= (GLushort
*) values
;
88 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
89 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
90 ASSERT(count
<= MAX_WIDTH
);
93 rb
->Wrapped
->GetRow(ctx
, rb
->Wrapped
, count
, x
, y
, values8
);
95 /* convert 8bpp to 16bpp */
96 for (i
= 0; i
< 4 * count
; i
++) {
97 values16
[i
] = (values8
[i
] << 8) | values8
[i
];
103 GetValues_16wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
104 const GLint x
[], const GLint y
[], void *values
)
106 GLubyte values8
[MAX_WIDTH
* 4];
107 GLushort
*values16
= (GLushort
*) values
;
109 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
110 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
112 rb
->Wrapped
->GetValues(ctx
, rb
->Wrapped
, count
, x
, y
, values8
);
114 for (i
= 0; i
< 4 * count
; i
++) {
115 values16
[i
] = (values8
[i
] << 8) | values8
[i
];
121 PutRow_16wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
122 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
124 GLubyte values8
[MAX_WIDTH
* 4];
125 GLushort
*values16
= (GLushort
*) values
;
127 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
128 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
129 for (i
= 0; i
< 4 * count
; i
++) {
130 values8
[i
] = values16
[i
] >> 8;
132 rb
->Wrapped
->PutRow(ctx
, rb
->Wrapped
, count
, x
, y
, values8
, mask
);
137 PutRowRGB_16wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
138 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
140 GLubyte values8
[MAX_WIDTH
* 3];
141 GLushort
*values16
= (GLushort
*) values
;
143 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
144 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
145 for (i
= 0; i
< 3 * count
; i
++) {
146 values8
[i
] = values16
[i
] >> 8;
148 rb
->Wrapped
->PutRowRGB(ctx
, rb
->Wrapped
, count
, x
, y
, values8
, mask
);
153 PutMonoRow_16wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
154 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
157 GLushort
*value16
= (GLushort
*) value
;
158 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
159 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
160 value8
[0] = value16
[0] >> 8;
161 value8
[1] = value16
[1] >> 8;
162 value8
[2] = value16
[2] >> 8;
163 value8
[3] = value16
[3] >> 8;
164 rb
->Wrapped
->PutMonoRow(ctx
, rb
->Wrapped
, count
, x
, y
, value8
, mask
);
169 PutValues_16wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
170 const GLint x
[], const GLint y
[], const void *values
,
173 GLubyte values8
[MAX_WIDTH
* 4];
174 GLushort
*values16
= (GLushort
*) values
;
176 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
177 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
178 for (i
= 0; i
< 4 * count
; i
++) {
179 values8
[i
] = values16
[i
] >> 8;
181 rb
->Wrapped
->PutValues(ctx
, rb
->Wrapped
, count
, x
, y
, values8
, mask
);
186 PutMonoValues_16wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
187 GLuint count
, const GLint x
[], const GLint y
[],
188 const void *value
, const GLubyte
*mask
)
191 GLushort
*value16
= (GLushort
*) value
;
192 ASSERT(rb
->DataType
== GL_UNSIGNED_SHORT
);
193 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
194 value8
[0] = value16
[0] >> 8;
195 value8
[1] = value16
[1] >> 8;
196 value8
[2] = value16
[2] >> 8;
197 value8
[3] = value16
[3] >> 8;
198 rb
->Wrapped
->PutMonoValues(ctx
, rb
->Wrapped
, count
, x
, y
, value8
, mask
);
203 * Wrap an 8-bit/channel renderbuffer with a 16-bit/channel
204 * renderbuffer adaptor.
206 struct gl_renderbuffer
*
207 _mesa_new_renderbuffer_16wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb8
)
209 struct gl_renderbuffer
*rb16
;
211 rb16
= _mesa_new_renderbuffer(ctx
, rb8
->Name
);
213 ASSERT(rb8
->DataType
== GL_UNSIGNED_BYTE
);
214 ASSERT(rb8
->_BaseFormat
== GL_RGBA
);
216 _glthread_LOCK_MUTEX(rb8
->Mutex
);
218 _glthread_UNLOCK_MUTEX(rb8
->Mutex
);
220 rb16
->InternalFormat
= rb8
->InternalFormat
;
221 rb16
->Format
= rb8
->Format
; /* XXX is this right? */
222 rb16
->_BaseFormat
= rb8
->_BaseFormat
;
223 rb16
->DataType
= GL_UNSIGNED_SHORT
;
224 /* Note: passing through underlying bits/channel */
227 rb16
->AllocStorage
= AllocStorage_wrapper
;
228 rb16
->Delete
= Delete_wrapper
;
229 rb16
->GetPointer
= GetPointer_wrapper
;
230 rb16
->GetRow
= GetRow_16wrap8
;
231 rb16
->GetValues
= GetValues_16wrap8
;
232 rb16
->PutRow
= PutRow_16wrap8
;
233 rb16
->PutRowRGB
= PutRowRGB_16wrap8
;
234 rb16
->PutMonoRow
= PutMonoRow_16wrap8
;
235 rb16
->PutValues
= PutValues_16wrap8
;
236 rb16
->PutMonoValues
= PutMonoValues_16wrap8
;
245 GetRow_32wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
246 GLint x
, GLint y
, void *values
)
248 GLubyte values8
[MAX_WIDTH
* 4];
249 GLfloat
*values32
= (GLfloat
*) values
;
251 ASSERT(rb
->DataType
== GL_FLOAT
);
252 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
253 ASSERT(count
<= MAX_WIDTH
);
255 /* get 8bpp values */
256 rb
->Wrapped
->GetRow(ctx
, rb
->Wrapped
, count
, x
, y
, values8
);
258 /* convert 8bpp to 32bpp */
259 for (i
= 0; i
< 4 * count
; i
++) {
260 values32
[i
] = UBYTE_TO_FLOAT(values8
[i
]);
266 GetValues_32wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
267 const GLint x
[], const GLint y
[], void *values
)
269 GLubyte values8
[MAX_WIDTH
* 4];
270 GLfloat
*values32
= (GLfloat
*) values
;
272 ASSERT(rb
->DataType
== GL_FLOAT
);
273 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
275 rb
->Wrapped
->GetValues(ctx
, rb
->Wrapped
, count
, x
, y
, values8
);
277 for (i
= 0; i
< 4 * count
; i
++) {
278 values32
[i
] = UBYTE_TO_FLOAT(values8
[i
]);
284 PutRow_32wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
285 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
287 GLubyte values8
[MAX_WIDTH
* 4];
288 GLfloat
*values32
= (GLfloat
*) values
;
290 ASSERT(rb
->DataType
== GL_FLOAT
);
291 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
292 for (i
= 0; i
< 4 * count
; i
++) {
293 UNCLAMPED_FLOAT_TO_UBYTE(values8
[i
], values32
[i
]);
295 rb
->Wrapped
->PutRow(ctx
, rb
->Wrapped
, count
, x
, y
, values8
, mask
);
300 PutRowRGB_32wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
301 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
303 GLubyte values8
[MAX_WIDTH
* 3];
304 GLfloat
*values32
= (GLfloat
*) values
;
306 ASSERT(rb
->DataType
== GL_FLOAT
);
307 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
308 for (i
= 0; i
< 3 * count
; i
++) {
309 UNCLAMPED_FLOAT_TO_UBYTE(values8
[i
], values32
[i
]);
311 rb
->Wrapped
->PutRowRGB(ctx
, rb
->Wrapped
, count
, x
, y
, values8
, mask
);
316 PutMonoRow_32wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
317 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
320 GLfloat
*value32
= (GLfloat
*) value
;
321 ASSERT(rb
->DataType
== GL_FLOAT
);
322 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
323 UNCLAMPED_FLOAT_TO_UBYTE(value8
[0], value32
[0]);
324 UNCLAMPED_FLOAT_TO_UBYTE(value8
[1], value32
[1]);
325 UNCLAMPED_FLOAT_TO_UBYTE(value8
[2], value32
[2]);
326 UNCLAMPED_FLOAT_TO_UBYTE(value8
[3], value32
[3]);
327 rb
->Wrapped
->PutMonoRow(ctx
, rb
->Wrapped
, count
, x
, y
, value8
, mask
);
332 PutValues_32wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
333 const GLint x
[], const GLint y
[], const void *values
,
336 GLubyte values8
[MAX_WIDTH
* 4];
337 GLfloat
*values32
= (GLfloat
*) values
;
339 ASSERT(rb
->DataType
== GL_FLOAT
);
340 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
341 for (i
= 0; i
< 4 * count
; i
++) {
342 UNCLAMPED_FLOAT_TO_UBYTE(values8
[i
], values32
[i
]);
344 rb
->Wrapped
->PutValues(ctx
, rb
->Wrapped
, count
, x
, y
, values8
, mask
);
349 PutMonoValues_32wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
350 GLuint count
, const GLint x
[], const GLint y
[],
351 const void *value
, const GLubyte
*mask
)
354 GLfloat
*value32
= (GLfloat
*) value
;
355 ASSERT(rb
->DataType
== GL_FLOAT
);
356 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_BYTE
);
357 UNCLAMPED_FLOAT_TO_UBYTE(value8
[0], value32
[0]);
358 UNCLAMPED_FLOAT_TO_UBYTE(value8
[1], value32
[1]);
359 UNCLAMPED_FLOAT_TO_UBYTE(value8
[2], value32
[2]);
360 UNCLAMPED_FLOAT_TO_UBYTE(value8
[3], value32
[3]);
361 rb
->Wrapped
->PutMonoValues(ctx
, rb
->Wrapped
, count
, x
, y
, value8
, mask
);
366 * Wrap an 8-bit/channel renderbuffer with a 32-bit/channel
367 * renderbuffer adaptor.
369 struct gl_renderbuffer
*
370 _mesa_new_renderbuffer_32wrap8(GLcontext
*ctx
, struct gl_renderbuffer
*rb8
)
372 struct gl_renderbuffer
*rb32
;
374 rb32
= _mesa_new_renderbuffer(ctx
, rb8
->Name
);
376 ASSERT(rb8
->DataType
== GL_UNSIGNED_BYTE
);
377 ASSERT(rb8
->_BaseFormat
== GL_RGBA
);
379 _glthread_LOCK_MUTEX(rb8
->Mutex
);
381 _glthread_UNLOCK_MUTEX(rb8
->Mutex
);
383 rb32
->InternalFormat
= rb8
->InternalFormat
;
384 rb32
->Format
= rb8
->Format
; /* XXX is this right? */
385 rb32
->_BaseFormat
= rb8
->_BaseFormat
;
386 rb32
->DataType
= GL_FLOAT
;
387 /* Note: passing through underlying bits/channel */
390 rb32
->AllocStorage
= AllocStorage_wrapper
;
391 rb32
->Delete
= Delete_wrapper
;
392 rb32
->GetPointer
= GetPointer_wrapper
;
393 rb32
->GetRow
= GetRow_32wrap8
;
394 rb32
->GetValues
= GetValues_32wrap8
;
395 rb32
->PutRow
= PutRow_32wrap8
;
396 rb32
->PutRowRGB
= PutRowRGB_32wrap8
;
397 rb32
->PutMonoRow
= PutMonoRow_32wrap8
;
398 rb32
->PutValues
= PutValues_32wrap8
;
399 rb32
->PutMonoValues
= PutMonoValues_32wrap8
;
408 GetRow_32wrap16(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
409 GLint x
, GLint y
, void *values
)
411 GLushort values16
[MAX_WIDTH
* 4];
412 GLfloat
*values32
= (GLfloat
*) values
;
414 ASSERT(rb
->DataType
== GL_FLOAT
);
415 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_SHORT
);
416 ASSERT(count
<= MAX_WIDTH
);
418 /* get 16bpp values */
419 rb
->Wrapped
->GetRow(ctx
, rb
->Wrapped
, count
, x
, y
, values16
);
421 /* convert 16bpp to 32bpp */
422 for (i
= 0; i
< 4 * count
; i
++) {
423 values32
[i
] = USHORT_TO_FLOAT(values16
[i
]);
429 GetValues_32wrap16(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
430 const GLint x
[], const GLint y
[], void *values
)
432 GLushort values16
[MAX_WIDTH
* 4];
433 GLfloat
*values32
= (GLfloat
*) values
;
435 ASSERT(rb
->DataType
== GL_FLOAT
);
436 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_SHORT
);
438 rb
->Wrapped
->GetValues(ctx
, rb
->Wrapped
, count
, x
, y
, values16
);
440 for (i
= 0; i
< 4 * count
; i
++) {
441 values32
[i
] = USHORT_TO_FLOAT(values16
[i
]);
447 PutRow_32wrap16(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
448 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
450 GLushort values16
[MAX_WIDTH
* 4];
451 GLfloat
*values32
= (GLfloat
*) values
;
453 ASSERT(rb
->DataType
== GL_FLOAT
);
454 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_SHORT
);
455 for (i
= 0; i
< 4 * count
; i
++) {
456 UNCLAMPED_FLOAT_TO_USHORT(values16
[i
], values32
[i
]);
458 rb
->Wrapped
->PutRow(ctx
, rb
->Wrapped
, count
, x
, y
, values16
, mask
);
463 PutRowRGB_32wrap16(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
464 GLint x
, GLint y
, const void *values
, const GLubyte
*mask
)
466 GLushort values16
[MAX_WIDTH
* 3];
467 GLfloat
*values32
= (GLfloat
*) values
;
469 ASSERT(rb
->DataType
== GL_FLOAT
);
470 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_SHORT
);
471 for (i
= 0; i
< 3 * count
; i
++) {
472 UNCLAMPED_FLOAT_TO_USHORT(values16
[i
], values32
[i
]);
474 rb
->Wrapped
->PutRowRGB(ctx
, rb
->Wrapped
, count
, x
, y
, values16
, mask
);
479 PutMonoRow_32wrap16(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
480 GLint x
, GLint y
, const void *value
, const GLubyte
*mask
)
483 GLfloat
*value32
= (GLfloat
*) value
;
484 ASSERT(rb
->DataType
== GL_FLOAT
);
485 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_SHORT
);
486 UNCLAMPED_FLOAT_TO_USHORT(value16
[0], value32
[0]);
487 UNCLAMPED_FLOAT_TO_USHORT(value16
[1], value32
[1]);
488 UNCLAMPED_FLOAT_TO_USHORT(value16
[2], value32
[2]);
489 UNCLAMPED_FLOAT_TO_USHORT(value16
[3], value32
[3]);
490 rb
->Wrapped
->PutMonoRow(ctx
, rb
->Wrapped
, count
, x
, y
, value16
, mask
);
495 PutValues_32wrap16(GLcontext
*ctx
, struct gl_renderbuffer
*rb
, GLuint count
,
496 const GLint x
[], const GLint y
[], const void *values
,
499 GLushort values16
[MAX_WIDTH
* 4];
500 GLfloat
*values32
= (GLfloat
*) values
;
502 ASSERT(rb
->DataType
== GL_FLOAT
);
503 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_SHORT
);
504 for (i
= 0; i
< 4 * count
; i
++) {
505 UNCLAMPED_FLOAT_TO_USHORT(values16
[i
], values32
[i
]);
507 rb
->Wrapped
->PutValues(ctx
, rb
->Wrapped
, count
, x
, y
, values16
, mask
);
512 PutMonoValues_32wrap16(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
513 GLuint count
, const GLint x
[], const GLint y
[],
514 const void *value
, const GLubyte
*mask
)
517 GLfloat
*value32
= (GLfloat
*) value
;
518 ASSERT(rb
->DataType
== GL_FLOAT
);
519 ASSERT(rb
->Wrapped
->DataType
== GL_UNSIGNED_SHORT
);
520 UNCLAMPED_FLOAT_TO_USHORT(value16
[0], value32
[0]);
521 UNCLAMPED_FLOAT_TO_USHORT(value16
[1], value32
[1]);
522 UNCLAMPED_FLOAT_TO_USHORT(value16
[2], value32
[2]);
523 UNCLAMPED_FLOAT_TO_USHORT(value16
[3], value32
[3]);
524 rb
->Wrapped
->PutMonoValues(ctx
, rb
->Wrapped
, count
, x
, y
, value16
, mask
);
529 * Wrap an 16-bit/channel renderbuffer with a 32-bit/channel
530 * renderbuffer adaptor.
532 struct gl_renderbuffer
*
533 _mesa_new_renderbuffer_32wrap16(GLcontext
*ctx
, struct gl_renderbuffer
*rb16
)
535 struct gl_renderbuffer
*rb32
;
537 rb32
= _mesa_new_renderbuffer(ctx
, rb16
->Name
);
539 ASSERT(rb16
->DataType
== GL_UNSIGNED_SHORT
);
540 ASSERT(rb16
->_BaseFormat
== GL_RGBA
);
542 _glthread_LOCK_MUTEX(rb16
->Mutex
);
544 _glthread_UNLOCK_MUTEX(rb16
->Mutex
);
546 rb32
->InternalFormat
= rb16
->InternalFormat
;
547 rb32
->Format
= rb16
->Format
; /* XXX is this right? */
548 rb32
->_BaseFormat
= rb16
->_BaseFormat
;
549 rb32
->DataType
= GL_FLOAT
;
550 /* Note: passing through underlying bits/channel */
551 rb32
->Wrapped
= rb16
;
553 rb32
->AllocStorage
= AllocStorage_wrapper
;
554 rb32
->Delete
= Delete_wrapper
;
555 rb32
->GetPointer
= GetPointer_wrapper
;
556 rb32
->GetRow
= GetRow_32wrap16
;
557 rb32
->GetValues
= GetValues_32wrap16
;
558 rb32
->PutRow
= PutRow_32wrap16
;
559 rb32
->PutRowRGB
= PutRowRGB_32wrap16
;
560 rb32
->PutMonoRow
= PutMonoRow_32wrap16
;
561 rb32
->PutValues
= PutValues_32wrap16
;
562 rb32
->PutMonoValues
= PutMonoValues_32wrap16
;