1/* 2 * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22 23#ifndef _NINE_PIPE_H_ 24#define _NINE_PIPE_H_ 25 26#include "d3d9.h" 27#include "pipe/p_format.h" 28#include "pipe/p_screen.h" 29#include "pipe/p_state.h" /* pipe_box */ 30#include "util/macros.h" 31#include "util/u_rect.h" 32#include "util/format/u_format.h" 33#include "nine_helpers.h" 34 35struct cso_context; 36 37extern const enum pipe_format nine_d3d9_to_pipe_format_map[120]; 38extern const D3DFORMAT nine_pipe_to_d3d9_format_map[PIPE_FORMAT_COUNT]; 39 40void nine_convert_dsa_state(struct pipe_depth_stencil_alpha_state *, const DWORD *); 41void nine_convert_rasterizer_state(struct NineDevice9 *, struct pipe_rasterizer_state *, const DWORD *); 42void nine_convert_blend_state(struct pipe_blend_state *, const DWORD *); 43void nine_convert_sampler_state(struct cso_context *, int idx, const DWORD *); 44 45#define is_ATI1_ATI2(format) (format == PIPE_FORMAT_RGTC1_UNORM || format == PIPE_FORMAT_RGTC2_UNORM) 46 47static inline void 48rect_to_pipe_box(struct pipe_box *dst, const RECT *src) 49{ 50 dst->x = src->left; 51 dst->y = src->top; 52 dst->z = 0; 53 dst->width = src->right - src->left; 54 dst->height = src->bottom - src->top; 55 dst->depth = 1; 56} 57 58static inline void 59pipe_box_to_rect(RECT *dst, const struct pipe_box *src) 60{ 61 dst->left = src->x; 62 dst->right = src->x + src->width; 63 dst->top = src->y; 64 dst->bottom = src->y + src->height; 65} 66 67static inline void 68rect_minify_inclusive(RECT *rect) 69{ 70 rect->left = rect->left >> 2; 71 rect->top = rect->top >> 2; 72 rect->right = DIV_ROUND_UP(rect->right, 2); 73 rect->bottom = DIV_ROUND_UP(rect->bottom, 2); 74} 75 76/* We suppose: 77 * 0 <= rect->left < rect->right 78 * 0 <= rect->top < rect->bottom 79 */ 80static inline void 81fit_rect_format_inclusive(enum pipe_format format, RECT *rect, int width, int height) 82{ 83 const unsigned w = util_format_get_blockwidth(format); 84 const unsigned h = util_format_get_blockheight(format); 85 86 if (util_format_is_compressed(format)) { 87 rect->left = rect->left - rect->left % w; 88 rect->top = rect->top - rect->top % h; 89 rect->right = (rect->right % w) == 0 ? 90 rect->right : 91 rect->right - (rect->right % w) + w; 92 rect->bottom = (rect->bottom % h) == 0 ? 93 rect->bottom : 94 rect->bottom - (rect->bottom % h) + h; 95 } 96 97 rect->right = MIN2(rect->right, width); 98 rect->bottom = MIN2(rect->bottom, height); 99} 100 101static inline boolean 102rect_to_pipe_box_clamp(struct pipe_box *dst, const RECT *src) 103{ 104 rect_to_pipe_box(dst, src); 105 106 if (dst->width <= 0 || dst->height <= 0) { 107 DBG_FLAG(DBG_UNKNOWN, "Warning: NULL box"); 108 dst->width = MAX2(dst->width, 0); 109 dst->height = MAX2(dst->height, 0); 110 return TRUE; 111 } 112 return FALSE; 113} 114 115static inline boolean 116rect_to_pipe_box_flip(struct pipe_box *dst, const RECT *src) 117{ 118 rect_to_pipe_box(dst, src); 119 120 if (dst->width >= 0 && dst->height >= 0) 121 return FALSE; 122 if (dst->width < 0) dst->width = -dst->width; 123 if (dst->height < 0) dst->height = -dst->height; 124 return TRUE; 125} 126 127static inline void 128rect_to_pipe_box_xy_only(struct pipe_box *dst, const RECT *src) 129{ 130 user_warn(src->left > src->right || src->top > src->bottom); 131 132 dst->x = src->left; 133 dst->y = src->top; 134 dst->width = src->right - src->left; 135 dst->height = src->bottom - src->top; 136} 137 138static inline boolean 139rect_to_pipe_box_xy_only_clamp(struct pipe_box *dst, const RECT *src) 140{ 141 rect_to_pipe_box_xy_only(dst, src); 142 143 if (dst->width <= 0 || dst->height <= 0) { 144 DBG_FLAG(DBG_UNKNOWN, "Warning: NULL box"); 145 dst->width = MAX2(dst->width, 0); 146 dst->height = MAX2(dst->height, 0); 147 return TRUE; 148 } 149 return FALSE; 150} 151 152static inline void 153rect_to_g3d_u_rect(struct u_rect *dst, const RECT *src) 154{ 155 user_warn(src->left > src->right || src->top > src->bottom); 156 157 dst->x0 = src->left; 158 dst->x1 = src->right; 159 dst->y0 = src->top; 160 dst->y1 = src->bottom; 161} 162 163static inline void 164d3dbox_to_pipe_box(struct pipe_box *dst, const D3DBOX *src) 165{ 166 user_warn(src->Left > src->Right); 167 user_warn(src->Top > src->Bottom); 168 user_warn(src->Front > src->Back); 169 170 dst->x = src->Left; 171 dst->y = src->Top; 172 dst->z = src->Front; 173 dst->width = src->Right - src->Left; 174 dst->height = src->Bottom - src->Top; 175 dst->depth = src->Back - src->Front; 176} 177 178static inline D3DFORMAT 179pipe_to_d3d9_format(enum pipe_format format) 180{ 181 return nine_pipe_to_d3d9_format_map[format]; 182} 183 184static inline boolean 185fetch4_compatible_format( D3DFORMAT fmt ) 186{ 187 /* Basically formats with only red channel are allowed (with some exceptions) */ 188 static const D3DFORMAT allowed[] = { /* TODO: list incomplete */ 189 D3DFMT_L8, 190 D3DFMT_L16, 191 D3DFMT_R16F, 192 D3DFMT_R32F, 193 D3DFMT_A8, 194 D3DFMT_DF16, 195 D3DFMT_DF24, 196 D3DFMT_INTZ 197 }; 198 unsigned i; 199 200 for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) { 201 if (fmt == allowed[i]) { return TRUE; } 202 } 203 return FALSE; 204} 205 206/* ATI1 and ATI2 are not officially compressed in d3d9 */ 207static inline boolean 208compressed_format( D3DFORMAT fmt ) 209{ 210 switch (fmt) { 211 case D3DFMT_DXT1: 212 case D3DFMT_DXT2: 213 case D3DFMT_DXT3: 214 case D3DFMT_DXT4: 215 case D3DFMT_DXT5: 216 return TRUE; 217 default: 218 break; 219 } 220 return FALSE; 221} 222 223static inline boolean 224depth_stencil_format( D3DFORMAT fmt ) 225{ 226 static const D3DFORMAT allowed[] = { 227 D3DFMT_D16_LOCKABLE, 228 D3DFMT_D32, 229 D3DFMT_D15S1, 230 D3DFMT_D24S8, 231 D3DFMT_D24X8, 232 D3DFMT_D24X4S4, 233 D3DFMT_D16, 234 D3DFMT_D32F_LOCKABLE, 235 D3DFMT_D24FS8, 236 D3DFMT_D32_LOCKABLE, 237 D3DFMT_DF16, 238 D3DFMT_DF24, 239 D3DFMT_INTZ 240 }; 241 unsigned i; 242 243 for (i = 0; i < sizeof(allowed)/sizeof(D3DFORMAT); i++) { 244 if (fmt == allowed[i]) { return TRUE; } 245 } 246 return FALSE; 247} 248 249static inline unsigned 250d3d9_get_pipe_depth_format_bindings(D3DFORMAT format) 251{ 252 switch (format) { 253 case D3DFMT_D32: 254 case D3DFMT_D15S1: 255 case D3DFMT_D24S8: 256 case D3DFMT_D24X8: 257 case D3DFMT_D24X4S4: 258 case D3DFMT_D16: 259 case D3DFMT_D24FS8: 260 return PIPE_BIND_DEPTH_STENCIL; 261 case D3DFMT_D32F_LOCKABLE: 262 case D3DFMT_D16_LOCKABLE: 263 case D3DFMT_D32_LOCKABLE: 264 return PIPE_BIND_DEPTH_STENCIL; 265 case D3DFMT_DF16: 266 case D3DFMT_DF24: 267 case D3DFMT_INTZ: 268 return PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_SAMPLER_VIEW; 269 default: unreachable("Unexpected format"); 270 } 271} 272 273static inline enum pipe_format 274d3d9_to_pipe_format_internal(D3DFORMAT format) 275{ 276 if (format <= D3DFMT_A2B10G10R10_XR_BIAS) 277 return nine_d3d9_to_pipe_format_map[format]; 278 switch (format) { 279 case D3DFMT_INTZ: return PIPE_FORMAT_S8_UINT_Z24_UNORM; 280 case D3DFMT_DF16: return PIPE_FORMAT_Z16_UNORM; 281 case D3DFMT_DF24: return PIPE_FORMAT_X8Z24_UNORM; 282 case D3DFMT_DXT1: return PIPE_FORMAT_DXT1_RGBA; 283 case D3DFMT_DXT2: return PIPE_FORMAT_DXT3_RGBA; /* XXX */ 284 case D3DFMT_DXT3: return PIPE_FORMAT_DXT3_RGBA; 285 case D3DFMT_DXT4: return PIPE_FORMAT_DXT5_RGBA; /* XXX */ 286 case D3DFMT_DXT5: return PIPE_FORMAT_DXT5_RGBA; 287 case D3DFMT_ATI1: return PIPE_FORMAT_RGTC1_UNORM; 288 case D3DFMT_ATI2: return PIPE_FORMAT_RGTC2_UNORM; 289 case D3DFMT_UYVY: return PIPE_FORMAT_UYVY; 290 case D3DFMT_YUY2: return PIPE_FORMAT_YUYV; /* XXX check */ 291 case D3DFMT_NV12: return PIPE_FORMAT_NV12; 292 case D3DFMT_G8R8_G8B8: return PIPE_FORMAT_G8R8_G8B8_UNORM; /* XXX order ? */ 293 case D3DFMT_R8G8_B8G8: return PIPE_FORMAT_R8G8_B8G8_UNORM; /* XXX order ? */ 294 case D3DFMT_BINARYBUFFER: return PIPE_FORMAT_NONE; /* not a format */ 295 case D3DFMT_MULTI2_ARGB8: return PIPE_FORMAT_NONE; /* not supported */ 296 case D3DFMT_Y210: /* XXX */ 297 case D3DFMT_Y216: 298 case D3DFMT_NV11: 299 case D3DFMT_NULL: /* special cased, only for surfaces */ 300 return PIPE_FORMAT_NONE; 301 default: 302 DBG_FLAG(DBG_UNKNOWN, "unknown D3DFORMAT: 0x%x/%c%c%c%c\n", 303 format, (char)format, (char)(format >> 8), 304 (char)(format >> 16), (char)(format >> 24)); 305 return PIPE_FORMAT_NONE; 306 } 307} 308 309#define format_check_internal(pipe_format) \ 310 screen->is_format_supported(screen, pipe_format, target, \ 311 sample_count, sample_count, bindings) 312 313static inline enum pipe_format 314d3d9_to_pipe_format_checked(struct pipe_screen *screen, 315 D3DFORMAT format, 316 enum pipe_texture_target target, 317 unsigned sample_count, 318 unsigned bindings, 319 boolean srgb, 320 boolean bypass_check) 321{ 322 enum pipe_format result; 323 324 /* We cannot render to depth textures as a render target */ 325 if (depth_stencil_format(format) && (bindings & PIPE_BIND_RENDER_TARGET)) 326 return PIPE_FORMAT_NONE; 327 328 result = d3d9_to_pipe_format_internal(format); 329 if (result == PIPE_FORMAT_NONE) 330 return PIPE_FORMAT_NONE; 331 332 if (srgb) 333 result = util_format_srgb(result); 334 335 /* bypass_check: Used for D3DPOOL_SCRATCH, which 336 * isn't limited to the formats supported by the 337 * device, and to check we are not using a format 338 * fallback. */ 339 if (bypass_check || format_check_internal(result)) 340 return result; 341 342 /* fallback to another format for formats 343 * that match several pipe_format */ 344 switch(format) { 345 /* depth buffer formats are not lockable (except those for which it 346 * is precised in the name), so it is ok to match to another similar 347 * format. In all cases, if the app reads the texture with a shader, 348 * it gets depth on r and doesn't get stencil.*/ 349 case D3DFMT_INTZ: 350 case D3DFMT_D24S8: 351 if (format_check_internal(PIPE_FORMAT_Z24_UNORM_S8_UINT)) 352 return PIPE_FORMAT_Z24_UNORM_S8_UINT; 353 break; 354 case D3DFMT_DF24: 355 case D3DFMT_D24X8: 356 if (format_check_internal(PIPE_FORMAT_Z24X8_UNORM)) 357 return PIPE_FORMAT_Z24X8_UNORM; 358 break; 359 /* Support for X8L8V8U8 bumpenvmap format with lighting bits. 360 * X8L8V8U8 is commonly supported among dx9 cards. 361 * To avoid precision loss, we use PIPE_FORMAT_R32G32B32X32_FLOAT, 362 * however using PIPE_FORMAT_R8G8B8A8_SNORM should be ok */ 363 case D3DFMT_X8L8V8U8: 364 if (bindings & PIPE_BIND_RENDER_TARGET) 365 return PIPE_FORMAT_NONE; 366 if (format_check_internal(PIPE_FORMAT_R32G32B32X32_FLOAT)) 367 return PIPE_FORMAT_R32G32B32X32_FLOAT; 368 break; 369 /* Fallback for YUV formats */ 370 case D3DFMT_UYVY: 371 case D3DFMT_YUY2: 372 case D3DFMT_NV12: 373 if (bindings & PIPE_BIND_RENDER_TARGET) 374 return PIPE_FORMAT_NONE; 375 if (format_check_internal(PIPE_FORMAT_R8G8B8X8_UNORM)) 376 return PIPE_FORMAT_R8G8B8X8_UNORM; 377 default: 378 break; 379 } 380 return PIPE_FORMAT_NONE; 381} 382 383/* The quality levels are vendor dependent, so we set our own. 384 * Every quality level has its own sample count and sample 385 * position matrix. 386 * The exact mapping might differ from system to system but thats OK, 387 * as there's no way to gather more information about quality levels 388 * in D3D9. 389 * In case of NONMASKABLE multisample map every quality-level 390 * to a MASKABLE MultiSampleType: 391 * 0: no MSAA 392 * 1: 2x MSAA 393 * 2: 4x MSAA 394 * ... 395 * If the requested quality level is not available to nearest 396 * matching quality level is used. 397 * If no multisample is available the function sets 398 * multisample to D3DMULTISAMPLE_NONE and returns zero. 399 */ 400static inline HRESULT 401d3dmultisample_type_check(struct pipe_screen *screen, 402 D3DFORMAT format, 403 D3DMULTISAMPLE_TYPE *multisample, 404 DWORD multisamplequality, 405 DWORD *levels) 406{ 407 unsigned bind, i; 408 409 assert(multisample); 410 411 if (levels) 412 *levels = 1; 413 414 /* Ignores multisamplequality */ 415 if (*multisample == D3DMULTISAMPLE_NONE) 416 return D3D_OK; 417 418 if (*multisample == D3DMULTISAMPLE_NONMASKABLE) { 419 if (depth_stencil_format(format)) 420 bind = d3d9_get_pipe_depth_format_bindings(format); 421 else /* render-target */ 422 bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 423 424 *multisample = 0; 425 for (i = D3DMULTISAMPLE_2_SAMPLES; i < D3DMULTISAMPLE_16_SAMPLES && 426 multisamplequality; ++i) { 427 if (d3d9_to_pipe_format_checked(screen, format, PIPE_TEXTURE_2D, 428 i, bind, FALSE, FALSE) != PIPE_FORMAT_NONE) { 429 multisamplequality--; 430 if (levels) 431 (*levels)++; 432 *multisample = i; 433 } 434 } 435 } 436 /* Make sure to get an exact match */ 437 if (multisamplequality) 438 return D3DERR_INVALIDCALL; 439 return D3D_OK; 440} 441 442static inline const char * 443d3dformat_to_string(D3DFORMAT fmt) 444{ 445 switch (fmt) { 446 case D3DFMT_UNKNOWN: return "D3DFMT_UNKNOWN"; 447 case D3DFMT_R8G8B8: return "D3DFMT_R8G8B8"; 448 case D3DFMT_A8R8G8B8: return "D3DFMT_A8R8G8B8"; 449 case D3DFMT_X8R8G8B8: return "D3DFMT_X8R8G8B8"; 450 case D3DFMT_R5G6B5: return "D3DFMT_R5G6B5"; 451 case D3DFMT_X1R5G5B5: return "D3DFMT_X1R5G5B5"; 452 case D3DFMT_A1R5G5B5: return "D3DFMT_A1R5G5B5"; 453 case D3DFMT_A4R4G4B4: return "D3DFMT_A4R4G4B4"; 454 case D3DFMT_R3G3B2: return "D3DFMT_R3G3B2"; 455 case D3DFMT_A8: return "D3DFMT_A8"; 456 case D3DFMT_A8R3G3B2: return "D3DFMT_A8R3G3B2"; 457 case D3DFMT_X4R4G4B4: return "D3DFMT_X4R4G4B4"; 458 case D3DFMT_A2B10G10R10: return "D3DFMT_A2B10G10R10"; 459 case D3DFMT_A8B8G8R8: return "D3DFMT_A8B8G8R8"; 460 case D3DFMT_X8B8G8R8: return "D3DFMT_X8B8G8R8"; 461 case D3DFMT_G16R16: return "D3DFMT_G16R16"; 462 case D3DFMT_A2R10G10B10: return "D3DFMT_A2R10G10B10"; 463 case D3DFMT_A16B16G16R16: return "D3DFMT_A16B16G16R16"; 464 case D3DFMT_A8P8: return "D3DFMT_A8P8"; 465 case D3DFMT_P8: return "D3DFMT_P8"; 466 case D3DFMT_L8: return "D3DFMT_L8"; 467 case D3DFMT_A8L8: return "D3DFMT_A8L8"; 468 case D3DFMT_A4L4: return "D3DFMT_A4L4"; 469 case D3DFMT_V8U8: return "D3DFMT_V8U8"; 470 case D3DFMT_L6V5U5: return "D3DFMT_L6V5U5"; 471 case D3DFMT_X8L8V8U8: return "D3DFMT_X8L8V8U8"; 472 case D3DFMT_Q8W8V8U8: return "D3DFMT_Q8W8V8U8"; 473 case D3DFMT_V16U16: return "D3DFMT_V16U16"; 474 case D3DFMT_A2W10V10U10: return "D3DFMT_A2W10V10U10"; 475 case D3DFMT_UYVY: return "D3DFMT_UYVY"; 476 case D3DFMT_R8G8_B8G8: return "D3DFMT_R8G8_B8G8"; 477 case D3DFMT_YUY2: return "D3DFMT_YUY2"; 478 case D3DFMT_G8R8_G8B8: return "D3DFMT_G8R8_G8B8"; 479 case D3DFMT_DXT1: return "D3DFMT_DXT1"; 480 case D3DFMT_DXT2: return "D3DFMT_DXT2"; 481 case D3DFMT_DXT3: return "D3DFMT_DXT3"; 482 case D3DFMT_DXT4: return "D3DFMT_DXT4"; 483 case D3DFMT_DXT5: return "D3DFMT_DXT5"; 484 case D3DFMT_ATI1: return "D3DFMT_ATI1"; 485 case D3DFMT_ATI2: return "D3DFMT_ATI2"; 486 case D3DFMT_D16_LOCKABLE: return "D3DFMT_D16_LOCKABLE"; 487 case D3DFMT_D32: return "D3DFMT_D32"; 488 case D3DFMT_D15S1: return "D3DFMT_D15S1"; 489 case D3DFMT_D24S8: return "D3DFMT_D24S8"; 490 case D3DFMT_D24X8: return "D3DFMT_D24X8"; 491 case D3DFMT_D24X4S4: return "D3DFMT_D24X4S4"; 492 case D3DFMT_D16: return "D3DFMT_D16"; 493 case D3DFMT_D32F_LOCKABLE: return "D3DFMT_D32F_LOCKABLE"; 494 case D3DFMT_D24FS8: return "D3DFMT_D24FS8"; 495 case D3DFMT_D32_LOCKABLE: return "D3DFMT_D32_LOCKABLE"; 496 case D3DFMT_S8_LOCKABLE: return "D3DFMT_S8_LOCKABLE"; 497 case D3DFMT_L16: return "D3DFMT_L16"; 498 case D3DFMT_VERTEXDATA: return "D3DFMT_VERTEXDATA"; 499 case D3DFMT_INDEX16: return "D3DFMT_INDEX16"; 500 case D3DFMT_INDEX32: return "D3DFMT_INDEX32"; 501 case D3DFMT_Q16W16V16U16: return "D3DFMT_Q16W16V16U16"; 502 case D3DFMT_MULTI2_ARGB8: return "D3DFMT_MULTI2_ARGB8"; 503 case D3DFMT_R16F: return "D3DFMT_R16F"; 504 case D3DFMT_G16R16F: return "D3DFMT_G16R16F"; 505 case D3DFMT_A16B16G16R16F: return "D3DFMT_A16B16G16R16F"; 506 case D3DFMT_R32F: return "D3DFMT_R32F"; 507 case D3DFMT_G32R32F: return "D3DFMT_G32R32F"; 508 case D3DFMT_A32B32G32R32F: return "D3DFMT_A32B32G32R32F"; 509 case D3DFMT_CxV8U8: return "D3DFMT_CxV8U8"; 510 case D3DFMT_A1: return "D3DFMT_A1"; 511 case D3DFMT_A2B10G10R10_XR_BIAS: return "D3DFMT_A2B10G10R10_XR_BIAS"; 512 case D3DFMT_BINARYBUFFER: return "D3DFMT_BINARYBUFFER"; 513 case D3DFMT_DF16: return "D3DFMT_DF16"; 514 case D3DFMT_DF24: return "D3DFMT_DF24"; 515 case D3DFMT_INTZ: return "D3DFMT_INTZ"; 516 case D3DFMT_NVDB: return "D3DFMT_NVDB"; 517 case D3DFMT_RESZ: return "D3DFMT_RESZ"; 518 case D3DFMT_NULL: return "D3DFMT_NULL"; 519 case D3DFMT_ATOC: return "D3DFMT_ATOC"; 520 default: 521 break; 522 } 523 return "Unknown"; 524} 525 526static inline unsigned 527nine_fvf_stride( DWORD fvf ) 528{ 529 unsigned texcount, i, size = 0; 530 531 switch (fvf & D3DFVF_POSITION_MASK) { 532 case D3DFVF_XYZ: size += 3*4; break; 533 case D3DFVF_XYZRHW: size += 4*4; break; 534 case D3DFVF_XYZB1: size += 4*4; break; 535 case D3DFVF_XYZB2: size += 5*4; break; 536 case D3DFVF_XYZB3: size += 6*4; break; 537 case D3DFVF_XYZB4: size += 7*4; break; 538 case D3DFVF_XYZB5: size += 8*4; break; 539 case D3DFVF_XYZW: size += 4*4; break; 540 default: 541 user_warn("Position doesn't match any known combination."); 542 break; 543 } 544 545 if (fvf & D3DFVF_NORMAL) { size += 3*4; } 546 if (fvf & D3DFVF_PSIZE) { size += 1*4; } 547 if (fvf & D3DFVF_DIFFUSE) { size += 1*4; } 548 if (fvf & D3DFVF_SPECULAR) { size += 1*4; } 549 550 texcount = (fvf >> D3DFVF_TEXCOUNT_SHIFT) & D3DFVF_TEXCOUNT_MASK; 551 if (user_error(texcount <= 8)) 552 texcount = 8; 553 554 for (i = 0; i < texcount; ++i) { 555 unsigned texformat = (fvf>>(16+i*2))&0x3; 556 /* texformats are defined having been shifted around so 1=3,2=0,3=1,4=2 557 * meaning we can just do this instead of the switch below */ 558 size += (((texformat+1)&0x3)+1)*4; 559 560 /* 561 switch (texformat) { 562 case D3DFVF_TEXTUREFORMAT1: size += 1*4; 563 case D3DFVF_TEXTUREFORMAT2: size += 2*4; 564 case D3DFVF_TEXTUREFORMAT3: size += 3*4; 565 case D3DFVF_TEXTUREFORMAT4: size += 4*4; 566 } 567 */ 568 } 569 570 return size; 571} 572 573static inline void 574d3dcolor_to_rgba(float *rgba, D3DCOLOR color) 575{ 576 rgba[0] = (float)((color >> 16) & 0xFF) / 0xFF; 577 rgba[1] = (float)((color >> 8) & 0xFF) / 0xFF; 578 rgba[2] = (float)((color >> 0) & 0xFF) / 0xFF; 579 rgba[3] = (float)((color >> 24) & 0xFF) / 0xFF; 580} 581 582static inline void 583d3dcolor_to_pipe_color_union(union pipe_color_union *rgba, D3DCOLOR color) 584{ 585 d3dcolor_to_rgba(&rgba->f[0], color); 586} 587 588static inline unsigned 589d3dprimitivetype_to_pipe_prim(D3DPRIMITIVETYPE prim) 590{ 591 switch (prim) { 592 case D3DPT_POINTLIST: return PIPE_PRIM_POINTS; 593 case D3DPT_LINELIST: return PIPE_PRIM_LINES; 594 case D3DPT_LINESTRIP: return PIPE_PRIM_LINE_STRIP; 595 case D3DPT_TRIANGLELIST: return PIPE_PRIM_TRIANGLES; 596 case D3DPT_TRIANGLESTRIP: return PIPE_PRIM_TRIANGLE_STRIP; 597 case D3DPT_TRIANGLEFAN: return PIPE_PRIM_TRIANGLE_FAN; 598 default: 599 assert(0); 600 return PIPE_PRIM_POINTS; 601 } 602} 603 604static inline unsigned 605prim_count_to_vertex_count(D3DPRIMITIVETYPE prim, UINT count) 606{ 607 switch (prim) { 608 case D3DPT_POINTLIST: return count; 609 case D3DPT_LINELIST: return count * 2; 610 case D3DPT_LINESTRIP: return count + 1; 611 case D3DPT_TRIANGLELIST: return count * 3; 612 case D3DPT_TRIANGLESTRIP: return count + 2; 613 case D3DPT_TRIANGLEFAN: return count + 2; 614 default: 615 assert(0); 616 return 0; 617 } 618} 619 620static inline unsigned 621d3dcmpfunc_to_pipe_func(D3DCMPFUNC func) 622{ 623 switch (func) { 624 case D3DCMP_NEVER: return PIPE_FUNC_NEVER; 625 case D3DCMP_LESS: return PIPE_FUNC_LESS; 626 case D3DCMP_EQUAL: return PIPE_FUNC_EQUAL; 627 case D3DCMP_LESSEQUAL: return PIPE_FUNC_LEQUAL; 628 case D3DCMP_GREATER: return PIPE_FUNC_GREATER; 629 case D3DCMP_NOTEQUAL: return PIPE_FUNC_NOTEQUAL; 630 case D3DCMP_GREATEREQUAL: return PIPE_FUNC_GEQUAL; 631 case D3DCMP_ALWAYS: return PIPE_FUNC_ALWAYS; 632 case D3DCMP_NEVER_ZERO: return PIPE_FUNC_NEVER; // Tested on windows + ATI HD5770 633 default: 634 assert(0); 635 return PIPE_FUNC_NEVER; 636 } 637} 638 639static inline unsigned 640d3dstencilop_to_pipe_stencil_op(D3DSTENCILOP op) 641{ 642 switch (op) { 643 case D3DSTENCILOP_KEEP: return PIPE_STENCIL_OP_KEEP; 644 case D3DSTENCILOP_ZERO: return PIPE_STENCIL_OP_ZERO; 645 case D3DSTENCILOP_REPLACE: return PIPE_STENCIL_OP_REPLACE; 646 case D3DSTENCILOP_INCRSAT: return PIPE_STENCIL_OP_INCR; 647 case D3DSTENCILOP_DECRSAT: return PIPE_STENCIL_OP_DECR; 648 case D3DSTENCILOP_INVERT: return PIPE_STENCIL_OP_INVERT; 649 case D3DSTENCILOP_INCR: return PIPE_STENCIL_OP_INCR_WRAP; 650 case D3DSTENCILOP_DECR: return PIPE_STENCIL_OP_DECR_WRAP; 651 default: 652 return PIPE_STENCIL_OP_ZERO; 653 } 654} 655 656static inline unsigned 657d3dcull_to_pipe_face(D3DCULL cull) 658{ 659 switch (cull) { 660 case D3DCULL_NONE: return PIPE_FACE_NONE; 661 case D3DCULL_CW: return PIPE_FACE_FRONT; 662 case D3DCULL_CCW: return PIPE_FACE_BACK; 663 default: 664 assert(0); 665 return PIPE_FACE_NONE; 666 } 667} 668 669static inline unsigned 670d3dfillmode_to_pipe_polygon_mode(D3DFILLMODE mode) 671{ 672 switch (mode) { 673 case D3DFILL_POINT: return PIPE_POLYGON_MODE_POINT; 674 case D3DFILL_WIREFRAME: return PIPE_POLYGON_MODE_LINE; 675 case D3DFILL_SOLID: return PIPE_POLYGON_MODE_FILL; 676 case D3DFILL_SOLID_ZERO:return PIPE_POLYGON_MODE_FILL; 677 default: 678 assert(0); 679 return PIPE_POLYGON_MODE_FILL; 680 } 681} 682 683static inline unsigned 684d3dblendop_to_pipe_blend(D3DBLENDOP op) 685{ 686 switch (op) { 687 case D3DBLENDOP_ADD: return PIPE_BLEND_ADD; 688 case D3DBLENDOP_SUBTRACT: return PIPE_BLEND_SUBTRACT; 689 case D3DBLENDOP_REVSUBTRACT: return PIPE_BLEND_REVERSE_SUBTRACT; 690 case D3DBLENDOP_MIN: return PIPE_BLEND_MIN; 691 case D3DBLENDOP_MAX: return PIPE_BLEND_MAX; 692 default: 693 assert(0); 694 return PIPE_BLEND_ADD; 695 } 696} 697 698/* NOTE: The COLOR factors for are equal to the ALPHA ones for alpha. 699 * Drivers may check RGB and ALPHA factors for equality so we should not 700 * simply substitute the ALPHA variants. 701 */ 702static inline unsigned 703d3dblend_alpha_to_pipe_blendfactor(D3DBLEND b) 704{ 705 switch (b) { 706 case D3DBLEND_ZERO: return PIPE_BLENDFACTOR_ZERO; 707 case D3DBLEND_ONE: return PIPE_BLENDFACTOR_ONE; 708 case D3DBLEND_SRCCOLOR: return PIPE_BLENDFACTOR_SRC_COLOR/*ALPHA*/; 709 case D3DBLEND_INVSRCCOLOR: return PIPE_BLENDFACTOR_INV_SRC_COLOR/*ALPHA*/; 710 case D3DBLEND_SRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; 711 case D3DBLEND_INVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 712 case D3DBLEND_DESTALPHA: return PIPE_BLENDFACTOR_DST_ALPHA; 713 case D3DBLEND_INVDESTALPHA: return PIPE_BLENDFACTOR_INV_DST_ALPHA; 714 case D3DBLEND_DESTCOLOR: return PIPE_BLENDFACTOR_DST_COLOR/*ALPHA*/; 715 case D3DBLEND_INVDESTCOLOR: return PIPE_BLENDFACTOR_INV_DST_COLOR/*ALPHA*/; 716 case D3DBLEND_SRCALPHASAT: return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; 717 case D3DBLEND_BOTHSRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; 718 case D3DBLEND_BOTHINVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 719 case D3DBLEND_BLENDFACTOR: return PIPE_BLENDFACTOR_CONST_COLOR/*ALPHA*/; 720 case D3DBLEND_INVBLENDFACTOR: return PIPE_BLENDFACTOR_INV_CONST_COLOR/*ALPHA*/; 721 case D3DBLEND_SRCCOLOR2: return PIPE_BLENDFACTOR_ONE; /* XXX */ 722 case D3DBLEND_INVSRCCOLOR2: return PIPE_BLENDFACTOR_ZERO; /* XXX */ 723 default: 724 DBG_FLAG(DBG_UNKNOWN, "Unhandled blend factor %d\n", b); 725 return PIPE_BLENDFACTOR_ZERO; 726 } 727} 728 729static inline unsigned 730d3dblend_color_to_pipe_blendfactor(D3DBLEND b) 731{ 732 switch (b) { 733 case D3DBLEND_ZERO: return PIPE_BLENDFACTOR_ZERO; 734 case D3DBLEND_ONE: return PIPE_BLENDFACTOR_ONE; 735 case D3DBLEND_SRCCOLOR: return PIPE_BLENDFACTOR_SRC_COLOR; 736 case D3DBLEND_INVSRCCOLOR: return PIPE_BLENDFACTOR_INV_SRC_COLOR; 737 case D3DBLEND_SRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; 738 case D3DBLEND_INVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 739 case D3DBLEND_DESTALPHA: return PIPE_BLENDFACTOR_DST_ALPHA; 740 case D3DBLEND_INVDESTALPHA: return PIPE_BLENDFACTOR_INV_DST_ALPHA; 741 case D3DBLEND_DESTCOLOR: return PIPE_BLENDFACTOR_DST_COLOR; 742 case D3DBLEND_INVDESTCOLOR: return PIPE_BLENDFACTOR_INV_DST_COLOR; 743 case D3DBLEND_SRCALPHASAT: return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; 744 case D3DBLEND_BOTHSRCALPHA: return PIPE_BLENDFACTOR_SRC_ALPHA; 745 case D3DBLEND_BOTHINVSRCALPHA: return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 746 case D3DBLEND_BLENDFACTOR: return PIPE_BLENDFACTOR_CONST_COLOR; 747 case D3DBLEND_INVBLENDFACTOR: return PIPE_BLENDFACTOR_INV_CONST_COLOR; 748 case D3DBLEND_SRCCOLOR2: return PIPE_BLENDFACTOR_SRC1_COLOR; 749 case D3DBLEND_INVSRCCOLOR2: return PIPE_BLENDFACTOR_INV_SRC1_COLOR; 750 default: 751 DBG_FLAG(DBG_UNKNOWN, "Unhandled blend factor %d\n", b); 752 return PIPE_BLENDFACTOR_ZERO; 753 } 754} 755 756static inline unsigned 757d3dtextureaddress_to_pipe_tex_wrap(D3DTEXTUREADDRESS addr) 758{ 759 switch (addr) { 760 case D3DTADDRESS_WRAP: return PIPE_TEX_WRAP_REPEAT; 761 case D3DTADDRESS_MIRROR: return PIPE_TEX_WRAP_MIRROR_REPEAT; 762 case D3DTADDRESS_CLAMP: return PIPE_TEX_WRAP_CLAMP_TO_EDGE; 763 case D3DTADDRESS_BORDER: return PIPE_TEX_WRAP_CLAMP_TO_BORDER; 764 case D3DTADDRESS_MIRRORONCE: return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; 765 default: 766 assert(0); 767 return PIPE_TEX_WRAP_CLAMP_TO_EDGE; 768 } 769} 770 771static inline unsigned 772d3dtexturefiltertype_to_pipe_tex_filter(D3DTEXTUREFILTERTYPE filter) 773{ 774 switch (filter) { 775 case D3DTEXF_POINT: return PIPE_TEX_FILTER_NEAREST; 776 case D3DTEXF_LINEAR: return PIPE_TEX_FILTER_LINEAR; 777 case D3DTEXF_ANISOTROPIC: return PIPE_TEX_FILTER_LINEAR; 778 779 case D3DTEXF_NONE: 780 case D3DTEXF_PYRAMIDALQUAD: 781 case D3DTEXF_GAUSSIANQUAD: 782 case D3DTEXF_CONVOLUTIONMONO: 783 default: 784 assert(0); 785 return PIPE_TEX_FILTER_NEAREST; 786 } 787} 788 789static inline unsigned 790d3dtexturefiltertype_to_pipe_tex_mipfilter(D3DTEXTUREFILTERTYPE filter) 791{ 792 switch (filter) { 793 case D3DTEXF_NONE: return PIPE_TEX_MIPFILTER_NONE; 794 case D3DTEXF_POINT: return PIPE_TEX_FILTER_NEAREST; 795 case D3DTEXF_LINEAR: return PIPE_TEX_FILTER_LINEAR; 796 case D3DTEXF_ANISOTROPIC: return PIPE_TEX_FILTER_LINEAR; 797 798 case D3DTEXF_PYRAMIDALQUAD: 799 case D3DTEXF_GAUSSIANQUAD: 800 case D3DTEXF_CONVOLUTIONMONO: 801 default: 802 assert(0); 803 return PIPE_TEX_MIPFILTER_NONE; 804 } 805} 806 807static inline unsigned nine_format_get_stride(enum pipe_format format, 808 unsigned width) 809{ 810 unsigned stride = util_format_get_stride(format, width); 811 812 return align(stride, 4); 813} 814 815static inline unsigned nine_format_get_level_alloc_size(enum pipe_format format, 816 unsigned width, 817 unsigned height, 818 unsigned level) 819{ 820 unsigned w, h, size; 821 822 w = u_minify(width, level); 823 h = u_minify(height, level); 824 if (is_ATI1_ATI2(format)) { 825 /* For "unknown" formats like ATIx use width * height bytes */ 826 size = w * h; 827 } else if (format == PIPE_FORMAT_NONE) { /* D3DFMT_NULL */ 828 size = w * h * 4; 829 } else { 830 size = nine_format_get_stride(format, w) * 831 util_format_get_nblocksy(format, h); 832 } 833 834 return size; 835} 836 837static inline unsigned nine_format_get_size_and_offsets(enum pipe_format format, 838 unsigned *offsets, 839 unsigned width, 840 unsigned height, 841 unsigned last_level) 842{ 843 unsigned l, w, h, size = 0; 844 845 for (l = 0; l <= last_level; ++l) { 846 w = u_minify(width, l); 847 h = u_minify(height, l); 848 offsets[l] = size; 849 if (is_ATI1_ATI2(format)) { 850 /* For "unknown" formats like ATIx use width * height bytes */ 851 size += w * h; 852 } else { 853 size += nine_format_get_stride(format, w) * 854 util_format_get_nblocksy(format, h); 855 } 856 } 857 858 return size; 859} 860 861#endif /* _NINE_PIPE_H_ */ 862