1 /*
2  * Copyright 2009 VMware, Inc.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * on the rights to use, copy, modify, merge, publish, distribute, sub
9  * license, and/or sell copies of the Software, and to permit persons to whom
10  * the Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19  * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22  * USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 /*
26  * This file holds the function implementation for one of the rbug extensions.
27  * Prototypes and declerations of functions and structs is in the same folder
28  * in the header file matching this file's name.
29  *
30  * The functions starting rbug_send_* encodes a call to the write format and
31  * sends that to the supplied connection, while functions starting with
32  * rbug_demarshal_* demarshal data in the wire protocol.
33  *
34  * Functions ending with _reply are replies to requests.
35  */
36 
37 #include "c99_alloca.h"
38 
39 #include "rbug_internal.h"
40 #include "rbug_texture.h"
41 
rbug_send_texture_list(struct rbug_connection * __con,uint32_t * __serial)42 int rbug_send_texture_list(struct rbug_connection *__con,
43                            uint32_t *__serial)
44 {
45 	uint32_t __len = 0;
46 	uint32_t __pos = 0;
47 	uint8_t *__data = NULL;
48 	int __ret = 0;
49 
50 	LEN(8); /* header */
51 
52 	/* align */
53 	PAD(__len, 8);
54 
55 	__data = (uint8_t*)MALLOC(__len);
56 	if (!__data)
57 		return -ENOMEM;
58 
59 	WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_LIST));
60 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
61 
62 	/* final pad */
63 	PAD(__pos, 8);
64 
65 	if (__pos != __len) {
66 		__ret = -EINVAL;
67 	} else {
68 		rbug_connection_send_start(__con, RBUG_OP_TEXTURE_LIST, __len);
69 		rbug_connection_write(__con, __data, __len);
70 		__ret = rbug_connection_send_finish(__con, __serial);
71 	}
72 
73 	FREE(__data);
74 	return __ret;
75 }
76 
rbug_send_texture_info(struct rbug_connection * __con,rbug_texture_t texture,uint32_t * __serial)77 int rbug_send_texture_info(struct rbug_connection *__con,
78                            rbug_texture_t texture,
79                            uint32_t *__serial)
80 {
81 	uint32_t __len = 0;
82 	uint32_t __pos = 0;
83 	uint8_t *__data = NULL;
84 	int __ret = 0;
85 
86 	LEN(8); /* header */
87 	LEN(8); /* texture */
88 
89 	/* align */
90 	PAD(__len, 8);
91 
92 	__data = (uint8_t*)MALLOC(__len);
93 	if (!__data)
94 		return -ENOMEM;
95 
96 	WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_INFO));
97 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
98 	WRITE(8, rbug_texture_t, texture); /* texture */
99 
100 	/* final pad */
101 	PAD(__pos, 8);
102 
103 	if (__pos != __len) {
104 		__ret = -EINVAL;
105 	} else {
106 		rbug_connection_send_start(__con, RBUG_OP_TEXTURE_INFO, __len);
107 		rbug_connection_write(__con, __data, __len);
108 		__ret = rbug_connection_send_finish(__con, __serial);
109 	}
110 
111 	FREE(__data);
112 	return __ret;
113 }
114 
rbug_send_texture_write(struct rbug_connection * __con,rbug_texture_t texture,uint32_t face,uint32_t level,uint32_t zslice,uint32_t x,uint32_t y,uint32_t w,uint32_t h,uint8_t * data,uint32_t data_len,uint32_t stride,uint32_t * __serial)115 int rbug_send_texture_write(struct rbug_connection *__con,
116                             rbug_texture_t texture,
117                             uint32_t face,
118                             uint32_t level,
119                             uint32_t zslice,
120                             uint32_t x,
121                             uint32_t y,
122                             uint32_t w,
123                             uint32_t h,
124                             uint8_t *data,
125                             uint32_t data_len,
126                             uint32_t stride,
127                             uint32_t *__serial)
128 {
129 	uint32_t __len = 0;
130 	uint32_t __pos = 0;
131 	uint8_t *__data = NULL;
132 	int __ret = 0;
133 
134 	LEN(8); /* header */
135 	LEN(8); /* texture */
136 	LEN(4); /* face */
137 	LEN(4); /* level */
138 	LEN(4); /* zslice */
139 	LEN(4); /* x */
140 	LEN(4); /* y */
141 	LEN(4); /* w */
142 	LEN(4); /* h */
143 	LEN_ARRAY(1, data); /* data */
144 	LEN(4); /* stride */
145 
146 	/* align */
147 	PAD(__len, 8);
148 
149 	__data = (uint8_t*)MALLOC(__len);
150 	if (!__data)
151 		return -ENOMEM;
152 
153 	WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_WRITE));
154 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
155 	WRITE(8, rbug_texture_t, texture); /* texture */
156 	WRITE(4, uint32_t, face); /* face */
157 	WRITE(4, uint32_t, level); /* level */
158 	WRITE(4, uint32_t, zslice); /* zslice */
159 	WRITE(4, uint32_t, x); /* x */
160 	WRITE(4, uint32_t, y); /* y */
161 	WRITE(4, uint32_t, w); /* w */
162 	WRITE(4, uint32_t, h); /* h */
163 	WRITE_ARRAY(1, uint8_t, data); /* data */
164 	WRITE(4, uint32_t, stride); /* stride */
165 
166 	/* final pad */
167 	PAD(__pos, 8);
168 
169 	if (__pos != __len) {
170 		__ret = -EINVAL;
171 	} else {
172 		rbug_connection_send_start(__con, RBUG_OP_TEXTURE_WRITE, __len);
173 		rbug_connection_write(__con, __data, __len);
174 		__ret = rbug_connection_send_finish(__con, __serial);
175 	}
176 
177 	FREE(__data);
178 	return __ret;
179 }
180 
rbug_send_texture_read(struct rbug_connection * __con,rbug_texture_t texture,uint32_t face,uint32_t level,uint32_t zslice,uint32_t x,uint32_t y,uint32_t w,uint32_t h,uint32_t * __serial)181 int rbug_send_texture_read(struct rbug_connection *__con,
182                            rbug_texture_t texture,
183                            uint32_t face,
184                            uint32_t level,
185                            uint32_t zslice,
186                            uint32_t x,
187                            uint32_t y,
188                            uint32_t w,
189                            uint32_t h,
190                            uint32_t *__serial)
191 {
192 	uint32_t __len = 0;
193 	uint32_t __pos = 0;
194 	uint8_t *__data = NULL;
195 	int __ret = 0;
196 
197 	LEN(8); /* header */
198 	LEN(8); /* texture */
199 	LEN(4); /* face */
200 	LEN(4); /* level */
201 	LEN(4); /* zslice */
202 	LEN(4); /* x */
203 	LEN(4); /* y */
204 	LEN(4); /* w */
205 	LEN(4); /* h */
206 
207 	/* align */
208 	PAD(__len, 8);
209 
210 	__data = (uint8_t*)MALLOC(__len);
211 	if (!__data)
212 		return -ENOMEM;
213 
214 	WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_READ));
215 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
216 	WRITE(8, rbug_texture_t, texture); /* texture */
217 	WRITE(4, uint32_t, face); /* face */
218 	WRITE(4, uint32_t, level); /* level */
219 	WRITE(4, uint32_t, zslice); /* zslice */
220 	WRITE(4, uint32_t, x); /* x */
221 	WRITE(4, uint32_t, y); /* y */
222 	WRITE(4, uint32_t, w); /* w */
223 	WRITE(4, uint32_t, h); /* h */
224 
225 	/* final pad */
226 	PAD(__pos, 8);
227 
228 	if (__pos != __len) {
229 		__ret = -EINVAL;
230 	} else {
231 		rbug_connection_send_start(__con, RBUG_OP_TEXTURE_READ, __len);
232 		rbug_connection_write(__con, __data, __len);
233 		__ret = rbug_connection_send_finish(__con, __serial);
234 	}
235 
236 	FREE(__data);
237 	return __ret;
238 }
239 
rbug_send_texture_list_reply(struct rbug_connection * __con,uint32_t serial,rbug_texture_t * textures,uint32_t textures_len,uint32_t * __serial)240 int rbug_send_texture_list_reply(struct rbug_connection *__con,
241                                  uint32_t serial,
242                                  rbug_texture_t *textures,
243                                  uint32_t textures_len,
244                                  uint32_t *__serial)
245 {
246 	uint32_t __len = 0;
247 	uint32_t __pos = 0;
248 	uint8_t *__data = NULL;
249 	int __ret = 0;
250 
251 	LEN(8); /* header */
252 	LEN(4); /* serial */
253 	LEN_ARRAY(8, textures); /* textures */
254 
255 	/* align */
256 	PAD(__len, 8);
257 
258 	__data = (uint8_t*)MALLOC(__len);
259 	if (!__data)
260 		return -ENOMEM;
261 
262 	WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_LIST_REPLY));
263 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
264 	WRITE(4, uint32_t, serial); /* serial */
265 	WRITE_ARRAY(8, rbug_texture_t, textures); /* textures */
266 
267 	/* final pad */
268 	PAD(__pos, 8);
269 
270 	if (__pos != __len) {
271 		__ret = -EINVAL;
272 	} else {
273 		rbug_connection_send_start(__con, RBUG_OP_TEXTURE_LIST_REPLY, __len);
274 		rbug_connection_write(__con, __data, __len);
275 		__ret = rbug_connection_send_finish(__con, __serial);
276 	}
277 
278 	FREE(__data);
279 	return __ret;
280 }
281 
rbug_send_texture_info_reply(struct rbug_connection * __con,uint32_t serial,uint32_t target,uint32_t format,uint32_t * width,uint32_t width_len,uint16_t * h16,uint32_t height_len,uint16_t * d16,uint32_t depth_len,uint32_t blockw,uint32_t blockh,uint32_t blocksize,uint32_t last_level,uint32_t nr_samples,uint32_t tex_usage,uint32_t * __serial)282 int rbug_send_texture_info_reply(struct rbug_connection *__con,
283                                  uint32_t serial,
284                                  uint32_t target,
285                                  uint32_t format,
286                                  uint32_t *width,
287                                  uint32_t width_len,
288                                  uint16_t *h16,
289                                  uint32_t height_len,
290                                  uint16_t *d16,
291                                  uint32_t depth_len,
292                                  uint32_t blockw,
293                                  uint32_t blockh,
294                                  uint32_t blocksize,
295                                  uint32_t last_level,
296                                  uint32_t nr_samples,
297                                  uint32_t tex_usage,
298                                  uint32_t *__serial)
299 {
300 	uint32_t __len = 0;
301 	uint32_t __pos = 0;
302 	uint8_t *__data = NULL;
303 	int __ret = 0;
304 	uint32_t *height = alloca(sizeof(uint32_t) * height_len);
305 	uint32_t *depth = alloca(sizeof(uint32_t) * height_len);
306 
307 	LEN(8); /* header */
308 	LEN(4); /* serial */
309 	LEN(4); /* target */
310 	LEN(4); /* format */
311 	LEN_ARRAY(4, width); /* width */
312 	LEN_ARRAY(4, height); /* height */
313 	LEN_ARRAY(4, depth); /* depth */
314 	LEN(4); /* blockw */
315 	LEN(4); /* blockh */
316 	LEN(4); /* blocksize */
317 	LEN(4); /* last_level */
318 	LEN(4); /* nr_samples */
319 	LEN(4); /* tex_usage */
320 
321 	/* align */
322 	PAD(__len, 8);
323 
324 	__data = (uint8_t*)MALLOC(__len);
325 	if (!__data)
326 		return -ENOMEM;
327 
328 	for (int i = 0; i < height_len; i++)
329 		height[i] = h16[i];
330 	for (int i = 0; i < depth_len; i++)
331 		depth[i] = d16[i];
332 
333 	WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_INFO_REPLY));
334 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
335 	WRITE(4, uint32_t, serial); /* serial */
336 	WRITE(4, uint32_t, target); /* target */
337 	WRITE(4, uint32_t, format); /* format */
338 	WRITE_ARRAY(4, uint32_t, width); /* width */
339 	WRITE_ARRAY(4, uint32_t, height); /* height */
340 	WRITE_ARRAY(4, uint32_t, depth); /* depth */
341 	WRITE(4, uint32_t, blockw); /* blockw */
342 	WRITE(4, uint32_t, blockh); /* blockh */
343 	WRITE(4, uint32_t, blocksize); /* blocksize */
344 	WRITE(4, uint32_t, last_level); /* last_level */
345 	WRITE(4, uint32_t, nr_samples); /* nr_samples */
346 	WRITE(4, uint32_t, tex_usage); /* tex_usage */
347 
348 	/* final pad */
349 	PAD(__pos, 8);
350 
351 	if (__pos != __len) {
352 		__ret = -EINVAL;
353 	} else {
354 		rbug_connection_send_start(__con, RBUG_OP_TEXTURE_INFO_REPLY, __len);
355 		rbug_connection_write(__con, __data, __len);
356 		__ret = rbug_connection_send_finish(__con, __serial);
357 	}
358 
359 	FREE(__data);
360 	return __ret;
361 }
362 
rbug_send_texture_read_reply(struct rbug_connection * __con,uint32_t serial,uint32_t format,uint32_t blockw,uint32_t blockh,uint32_t blocksize,uint8_t * data,uint32_t data_len,uint32_t stride,uint32_t * __serial)363 int rbug_send_texture_read_reply(struct rbug_connection *__con,
364                                  uint32_t serial,
365                                  uint32_t format,
366                                  uint32_t blockw,
367                                  uint32_t blockh,
368                                  uint32_t blocksize,
369                                  uint8_t *data,
370                                  uint32_t data_len,
371                                  uint32_t stride,
372                                  uint32_t *__serial)
373 {
374 	uint32_t __len = 0;
375 	uint32_t __pos = 0;
376 	uint8_t *__data = NULL;
377 	int __ret = 0;
378 
379 	LEN(8); /* header */
380 	LEN(4); /* serial */
381 	LEN(4); /* format */
382 	LEN(4); /* blockw */
383 	LEN(4); /* blockh */
384 	LEN(4); /* blocksize */
385 	LEN_ARRAY(1, data); /* data */
386 	LEN(4); /* stride */
387 
388 	/* align */
389 	PAD(__len, 8);
390 
391 	__data = (uint8_t*)MALLOC(__len);
392 	if (!__data)
393 		return -ENOMEM;
394 
395 	WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_READ_REPLY));
396 	WRITE(4, uint32_t, ((uint32_t)(__len / 4)));
397 	WRITE(4, uint32_t, serial); /* serial */
398 	WRITE(4, uint32_t, format); /* format */
399 	WRITE(4, uint32_t, blockw); /* blockw */
400 	WRITE(4, uint32_t, blockh); /* blockh */
401 	WRITE(4, uint32_t, blocksize); /* blocksize */
402 	WRITE_ARRAY(1, uint8_t, data); /* data */
403 	WRITE(4, uint32_t, stride); /* stride */
404 
405 	/* final pad */
406 	PAD(__pos, 8);
407 
408 	if (__pos != __len) {
409 		__ret = -EINVAL;
410 	} else {
411 		rbug_connection_send_start(__con, RBUG_OP_TEXTURE_READ_REPLY, __len);
412 		rbug_connection_write(__con, __data, __len);
413 		__ret = rbug_connection_send_finish(__con, __serial);
414 	}
415 
416 	FREE(__data);
417 	return __ret;
418 }
419 
rbug_demarshal_texture_list(struct rbug_proto_header * header)420 struct rbug_proto_texture_list * rbug_demarshal_texture_list(struct rbug_proto_header *header)
421 {
422 	struct rbug_proto_texture_list *ret;
423 
424 	if (!header)
425 		return NULL;
426 	if (header->opcode != (int32_t)RBUG_OP_TEXTURE_LIST)
427 		return NULL;
428 
429 	ret = MALLOC(sizeof(*ret));
430 	if (!ret)
431 		return NULL;
432 
433 	ret->header.__message = header;
434 	ret->header.opcode = header->opcode;
435 
436 	return ret;
437 }
438 
rbug_demarshal_texture_info(struct rbug_proto_header * header)439 struct rbug_proto_texture_info * rbug_demarshal_texture_info(struct rbug_proto_header *header)
440 {
441 	uint32_t len = 0;
442 	uint32_t pos = 0;
443 	uint8_t *data =  NULL;
444 	struct rbug_proto_texture_info *ret;
445 
446 	if (!header)
447 		return NULL;
448 	if (header->opcode != (int32_t)RBUG_OP_TEXTURE_INFO)
449 		return NULL;
450 
451 	pos = 0;
452 	len = header->length * 4;
453 	data = (uint8_t*)&header[1];
454 	ret = MALLOC(sizeof(*ret));
455 	if (!ret)
456 		return NULL;
457 
458 	ret->header.__message = header;
459 	ret->header.opcode = header->opcode;
460 
461 	READ(8, rbug_texture_t, texture); /* texture */
462 
463 	return ret;
464 }
465 
rbug_demarshal_texture_write(struct rbug_proto_header * header)466 struct rbug_proto_texture_write * rbug_demarshal_texture_write(struct rbug_proto_header *header)
467 {
468 	uint32_t len = 0;
469 	uint32_t pos = 0;
470 	uint8_t *data =  NULL;
471 	struct rbug_proto_texture_write *ret;
472 
473 	if (!header)
474 		return NULL;
475 	if (header->opcode != (int32_t)RBUG_OP_TEXTURE_WRITE)
476 		return NULL;
477 
478 	pos = 0;
479 	len = header->length * 4;
480 	data = (uint8_t*)&header[1];
481 	ret = MALLOC(sizeof(*ret));
482 	if (!ret)
483 		return NULL;
484 
485 	ret->header.__message = header;
486 	ret->header.opcode = header->opcode;
487 
488 	READ(8, rbug_texture_t, texture); /* texture */
489 	READ(4, uint32_t, face); /* face */
490 	READ(4, uint32_t, level); /* level */
491 	READ(4, uint32_t, zslice); /* zslice */
492 	READ(4, uint32_t, x); /* x */
493 	READ(4, uint32_t, y); /* y */
494 	READ(4, uint32_t, w); /* w */
495 	READ(4, uint32_t, h); /* h */
496 	READ_ARRAY(1, uint8_t, data); /* data */
497 	READ(4, uint32_t, stride); /* stride */
498 
499 	return ret;
500 }
501 
rbug_demarshal_texture_read(struct rbug_proto_header * header)502 struct rbug_proto_texture_read * rbug_demarshal_texture_read(struct rbug_proto_header *header)
503 {
504 	uint32_t len = 0;
505 	uint32_t pos = 0;
506 	uint8_t *data =  NULL;
507 	struct rbug_proto_texture_read *ret;
508 
509 	if (!header)
510 		return NULL;
511 	if (header->opcode != (int32_t)RBUG_OP_TEXTURE_READ)
512 		return NULL;
513 
514 	pos = 0;
515 	len = header->length * 4;
516 	data = (uint8_t*)&header[1];
517 	ret = MALLOC(sizeof(*ret));
518 	if (!ret)
519 		return NULL;
520 
521 	ret->header.__message = header;
522 	ret->header.opcode = header->opcode;
523 
524 	READ(8, rbug_texture_t, texture); /* texture */
525 	READ(4, uint32_t, face); /* face */
526 	READ(4, uint32_t, level); /* level */
527 	READ(4, uint32_t, zslice); /* zslice */
528 	READ(4, uint32_t, x); /* x */
529 	READ(4, uint32_t, y); /* y */
530 	READ(4, uint32_t, w); /* w */
531 	READ(4, uint32_t, h); /* h */
532 
533 	return ret;
534 }
535 
rbug_demarshal_texture_list_reply(struct rbug_proto_header * header)536 struct rbug_proto_texture_list_reply * rbug_demarshal_texture_list_reply(struct rbug_proto_header *header)
537 {
538 	uint32_t len = 0;
539 	uint32_t pos = 0;
540 	uint8_t *data =  NULL;
541 	struct rbug_proto_texture_list_reply *ret;
542 
543 	if (!header)
544 		return NULL;
545 	if (header->opcode != (int32_t)RBUG_OP_TEXTURE_LIST_REPLY)
546 		return NULL;
547 
548 	pos = 0;
549 	len = header->length * 4;
550 	data = (uint8_t*)&header[1];
551 	ret = MALLOC(sizeof(*ret));
552 	if (!ret)
553 		return NULL;
554 
555 	ret->header.__message = header;
556 	ret->header.opcode = header->opcode;
557 
558 	READ(4, uint32_t, serial); /* serial */
559 	READ_ARRAY(8, rbug_texture_t, textures); /* textures */
560 
561 	return ret;
562 }
563 
rbug_demarshal_texture_info_reply(struct rbug_proto_header * header)564 struct rbug_proto_texture_info_reply * rbug_demarshal_texture_info_reply(struct rbug_proto_header *header)
565 {
566 	uint32_t len = 0;
567 	uint32_t pos = 0;
568 	uint8_t *data =  NULL;
569 	struct rbug_proto_texture_info_reply *ret;
570 
571 	if (!header)
572 		return NULL;
573 	if (header->opcode != (int32_t)RBUG_OP_TEXTURE_INFO_REPLY)
574 		return NULL;
575 
576 	pos = 0;
577 	len = header->length * 4;
578 	data = (uint8_t*)&header[1];
579 	ret = MALLOC(sizeof(*ret));
580 	if (!ret)
581 		return NULL;
582 
583 	ret->header.__message = header;
584 	ret->header.opcode = header->opcode;
585 
586 	READ(4, uint32_t, serial); /* serial */
587 	READ(4, uint32_t, target); /* target */
588 	READ(4, uint32_t, format); /* format */
589 	READ_ARRAY(4, uint32_t, width); /* width */
590 	READ_ARRAY(4, uint32_t, height); /* height */
591 	READ_ARRAY(4, uint32_t, depth); /* depth */
592 	READ(4, uint32_t, blockw); /* blockw */
593 	READ(4, uint32_t, blockh); /* blockh */
594 	READ(4, uint32_t, blocksize); /* blocksize */
595 	READ(4, uint32_t, last_level); /* last_level */
596 	READ(4, uint32_t, nr_samples); /* nr_samples */
597 	READ(4, uint32_t, tex_usage); /* tex_usage */
598 
599 	return ret;
600 }
601 
rbug_demarshal_texture_read_reply(struct rbug_proto_header * header)602 struct rbug_proto_texture_read_reply * rbug_demarshal_texture_read_reply(struct rbug_proto_header *header)
603 {
604 	uint32_t len = 0;
605 	uint32_t pos = 0;
606 	uint8_t *data =  NULL;
607 	struct rbug_proto_texture_read_reply *ret;
608 
609 	if (!header)
610 		return NULL;
611 	if (header->opcode != (int32_t)RBUG_OP_TEXTURE_READ_REPLY)
612 		return NULL;
613 
614 	pos = 0;
615 	len = header->length * 4;
616 	data = (uint8_t*)&header[1];
617 	ret = MALLOC(sizeof(*ret));
618 	if (!ret)
619 		return NULL;
620 
621 	ret->header.__message = header;
622 	ret->header.opcode = header->opcode;
623 
624 	READ(4, uint32_t, serial); /* serial */
625 	READ(4, uint32_t, format); /* format */
626 	READ(4, uint32_t, blockw); /* blockw */
627 	READ(4, uint32_t, blockh); /* blockh */
628 	READ(4, uint32_t, blocksize); /* blocksize */
629 	READ_ARRAY(1, uint8_t, data); /* data */
630 	READ(4, uint32_t, stride); /* stride */
631 
632 	return ret;
633 }
634