struct pipe_resource * nouveau_buffer_create(struct pipe_screen *pscreen, const struct pipe_resource *templ) { struct nouveau_screen *screen = nouveau_screen(pscreen); struct nv04_resource *buffer; boolean ret; buffer = CALLOC_STRUCT(nv04_resource); if (!buffer) return NULL; buffer->base = *templ; buffer->vtbl = &nouveau_buffer_vtbl; pipe_reference_init(&buffer->base.reference, 1); buffer->base.screen = pscreen; if (buffer->base.bind & (screen->vidmem_bindings & screen->sysmem_bindings)) { switch (buffer->base.usage) { case PIPE_USAGE_DEFAULT: case PIPE_USAGE_IMMUTABLE: case PIPE_USAGE_STATIC: buffer->domain = NOUVEAU_BO_VRAM; break; case PIPE_USAGE_DYNAMIC: /* For most apps, we'd have to do staging transfers to avoid sync * with this usage, and GART -> GART copies would be suboptimal. */ buffer->domain = NOUVEAU_BO_VRAM; break; case PIPE_USAGE_STAGING: case PIPE_USAGE_STREAM: buffer->domain = NOUVEAU_BO_GART; break; default: assert(0); break; } } else { if (buffer->base.bind & screen->vidmem_bindings) buffer->domain = NOUVEAU_BO_VRAM; else if (buffer->base.bind & screen->sysmem_bindings) buffer->domain = NOUVEAU_BO_GART; } ret = nouveau_buffer_allocate(screen, buffer, buffer->domain); if (ret == FALSE) goto fail; if (buffer->domain == NOUVEAU_BO_VRAM && screen->hint_buf_keep_sysmem_copy) nouveau_buffer_cache(NULL, buffer); return &buffer->base; fail: FREE(buffer); return NULL; }
struct nouveau_bo * nouveau_screen_bo_from_handle(struct pipe_screen *pscreen, struct winsys_handle *whandle, unsigned *out_stride) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nouveau_bo *bo = 0; int ret; if (whandle->type != DRM_API_HANDLE_TYPE_SHARED && whandle->type != DRM_API_HANDLE_TYPE_FD) { debug_printf("%s: attempt to import unsupported handle type %d\n", __FUNCTION__, whandle->type); return NULL; } if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) ret = nouveau_bo_name_ref(dev, whandle->handle, &bo); else ret = nouveau_bo_prime_handle_ref(dev, whandle->handle, &bo); if (ret) { debug_printf("%s: ref name 0x%08x failed with %d\n", __FUNCTION__, whandle->handle, ret); return NULL; } *out_stride = whandle->stride; return bo; }
static struct pipe_texture * nouveau_drm_pt_from_name(struct drm_api *api, struct pipe_screen *pscreen, struct pipe_texture *templ, const char *name, unsigned stride, unsigned handle) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct pipe_texture *pt; struct pipe_buffer *pb; int ret; pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*)); if (!pb) return NULL; ret = nouveau_bo_handle_ref(dev, handle, (struct nouveau_bo**)(pb+1)); if (ret) { debug_printf("%s: ref name 0x%08x failed with %d\n", __func__, handle, ret); FREE(pb); return NULL; } pipe_reference_init(&pb->reference, 1); pb->screen = pscreen; pb->alignment = 0; pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE | PIPE_BUFFER_USAGE_CPU_READ_WRITE; pb->size = nouveau_bo(pb)->size; pt = pscreen->texture_blanket(pscreen, templ, &stride, pb); pipe_buffer_reference(&pb, NULL); return pt; }
struct pipe_resource * nouveau_buffer_create(struct pipe_screen *pscreen, const struct pipe_resource *templ) { struct nouveau_screen *screen = nouveau_screen(pscreen); struct nv04_resource *buffer; boolean ret; buffer = CALLOC_STRUCT(nv04_resource); if (!buffer) return NULL; buffer->base = *templ; buffer->vtbl = &nouveau_buffer_vtbl; pipe_reference_init(&buffer->base.reference, 1); buffer->base.screen = pscreen; if ((buffer->base.bind & screen->sysmem_bindings) == screen->sysmem_bindings) ret = nouveau_buffer_allocate(screen, buffer, 0); else ret = nouveau_buffer_allocate(screen, buffer, NOUVEAU_BO_GART); if (ret == FALSE) goto fail; return &buffer->base; fail: FREE(buffer); return NULL; }
int nvc0_screen_get_video_param(struct pipe_screen *pscreen, enum pipe_video_profile profile, enum pipe_video_cap param) { switch (param) { case PIPE_VIDEO_CAP_SUPPORTED: return profile >= PIPE_VIDEO_PROFILE_MPEG1; case PIPE_VIDEO_CAP_NPOT_TEXTURES: return 1; case PIPE_VIDEO_CAP_MAX_WIDTH: case PIPE_VIDEO_CAP_MAX_HEIGHT: return nouveau_screen(pscreen)->device->chipset < 0xd0 ? 2048 : 4096; case PIPE_VIDEO_CAP_PREFERED_FORMAT: return PIPE_FORMAT_NV12; case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED: case PIPE_VIDEO_CAP_PREFERS_INTERLACED: return true; case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE: return false; default: debug_printf("unknown video param: %d\n", param); return 0; } }
static uint64_t nouveau_screen_get_timestamp(struct pipe_screen *pscreen) { int64_t cpu_time = os_time_get() * 1000; /* getparam of PTIMER_TIME takes about x10 as long (several usecs) */ return cpu_time + nouveau_screen(pscreen)->cpu_gpu_time_delta; }
static void nouveau_drm_destroy_winsys(struct pipe_winsys *s) { struct nouveau_winsys *nv_winsys = nouveau_winsys(s); struct nouveau_screen *nv_screen= nouveau_screen(nv_winsys->pscreen); if (nv_screen) nouveau_device_close(&nv_screen->device); FREE(nv_winsys); }
static const char * nouveau_screen_get_name(struct pipe_screen *pscreen) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; static char buffer[128]; util_snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); return buffer; }
static boolean nvc0_screen_is_format_supported(struct pipe_screen *pscreen, enum pipe_format format, enum pipe_texture_target target, unsigned sample_count, unsigned bindings) { const struct util_format_description *desc = util_format_description(format); if (sample_count > 8) return false; if (!(0x117 & (1 << sample_count))) /* 0, 1, 2, 4 or 8 */ return false; /* Short-circuit the rest of the logic -- this is used by the state tracker * to determine valid MS levels in a no-attachments scenario. */ if (format == PIPE_FORMAT_NONE && bindings & PIPE_BIND_RENDER_TARGET) return true; if (!util_format_is_supported(format, bindings)) return false; if ((bindings & PIPE_BIND_SAMPLER_VIEW) && (target != PIPE_BUFFER)) if (util_format_get_blocksizebits(format) == 3 * 32) return false; if (bindings & PIPE_BIND_LINEAR) if (util_format_is_depth_or_stencil(format) || (target != PIPE_TEXTURE_1D && target != PIPE_TEXTURE_2D && target != PIPE_TEXTURE_RECT) || sample_count > 1) return false; /* Restrict ETC2 and ASTC formats here. These are only supported on GK20A. */ if ((desc->layout == UTIL_FORMAT_LAYOUT_ETC || desc->layout == UTIL_FORMAT_LAYOUT_ASTC) && /* The claim is that this should work on GM107 but it doesn't. Need to * test further and figure out if it's a nouveau issue or a HW one. nouveau_screen(pscreen)->class_3d < GM107_3D_CLASS && */ nouveau_screen(pscreen)->class_3d != NVEA_3D_CLASS) return false; /* transfers & shared are always supported */ bindings &= ~(PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_LINEAR | PIPE_BIND_SHARED); return (( nvc0_format_table[format].usage | nvc0_vertex_format[format].usage) & bindings) == bindings; }
static void nv50_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence) { struct nouveau_screen *screen = nouveau_screen(pipe->screen); if (fence) nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence); PUSH_KICK(screen->pushbuf); }
struct nouveau_bo * nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment, unsigned usage, unsigned bind, unsigned size) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nouveau_bo *bo = NULL; uint32_t flags = NOUVEAU_BO_MAP, tile_mode = 0, tile_flags = 0; int ret; if (bind & PIPE_BIND_VERTEX_BUFFER) flags |= nouveau_screen(pscreen)->vertex_buffer_flags; else if (bind & PIPE_BIND_INDEX_BUFFER) flags |= nouveau_screen(pscreen)->index_buffer_flags; if (bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_SCANOUT | PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SAMPLER_VIEW)) { /* TODO: this may be incorrect or suboptimal */ if (!(bind & PIPE_BIND_SCANOUT)) flags |= NOUVEAU_BO_GART; if (usage != PIPE_USAGE_DYNAMIC) flags |= NOUVEAU_BO_VRAM; if (dev->chipset == 0x50 || dev->chipset >= 0x80) { if (bind & PIPE_BIND_DEPTH_STENCIL) tile_flags = 0x2800; else tile_flags = 0x7000; } } ret = nouveau_bo_new_tile(dev, flags, alignment, size, tile_mode, tile_flags, &bo); if (ret) return NULL; return bo; }
struct pipe_resource * nouveau_buffer_create(struct pipe_screen *pscreen, const struct pipe_resource *templ) { struct nouveau_screen *screen = nouveau_screen(pscreen); struct nv04_resource *buffer; boolean ret; buffer = CALLOC_STRUCT(nv04_resource); if (!buffer) return NULL; buffer->base = *templ; buffer->vtbl = &nouveau_buffer_vtbl; pipe_reference_init(&buffer->base.reference, 1); buffer->base.screen = pscreen; if (buffer->base.bind & (screen->vidmem_bindings & screen->sysmem_bindings)) { switch (buffer->base.usage) { case PIPE_USAGE_DEFAULT: case PIPE_USAGE_IMMUTABLE: case PIPE_USAGE_STATIC: buffer->domain = NOUVEAU_BO_VRAM; break; case PIPE_USAGE_DYNAMIC: case PIPE_USAGE_STAGING: case PIPE_USAGE_STREAM: buffer->domain = NOUVEAU_BO_GART; break; default: assert(0); break; } } else { if (buffer->base.bind & screen->vidmem_bindings) buffer->domain = NOUVEAU_BO_VRAM; else if (buffer->base.bind & screen->sysmem_bindings) buffer->domain = NOUVEAU_BO_GART; } ret = nouveau_buffer_allocate(screen, buffer, buffer->domain); if (ret == FALSE) goto fail; return &buffer->base; fail: FREE(buffer); return NULL; }
struct nouveau_bo * nouveau_screen_bo_user(struct pipe_screen *pscreen, void *ptr, unsigned bytes) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nouveau_bo *bo = NULL; int ret; ret = nouveau_bo_user(dev, ptr, bytes, &bo); if (ret) return NULL; return bo; }
static void nv50_flush(struct pipe_context *pipe, struct pipe_fence_handle **fence, unsigned flags) { struct nouveau_screen *screen = nouveau_screen(pipe->screen); if (fence) nouveau_fence_ref(screen->fence.current, (struct nouveau_fence **)fence); PUSH_KICK(screen->pushbuf); nouveau_context_update_frame_stats(nouveau_context(pipe)); }
static struct pipe_context * nouveau_drm_create_context(struct drm_api *api, struct pipe_screen *pscreen) { struct nouveau_winsys *nvws = nouveau_winsys_screen(pscreen); struct pipe_context *(*init)(struct pipe_screen *, unsigned); unsigned chipset = nouveau_screen(pscreen)->device->chipset; int i; switch (chipset & 0xf0) { case 0x00: init = nv04_create; break; case 0x10: init = nv10_create; break; case 0x20: init = nv20_create; break; case 0x30: init = nv30_create; break; case 0x40: case 0x60: init = nv40_create; break; case 0x80: case 0x90: case 0xa0: init = nv50_create; break; default: debug_printf("%s: unknown chipset nv%02x\n", __func__, chipset); return NULL; } /* Find a free slot for a pipe context, allocate a new one if needed */ for (i = 0; i < nvws->nr_pctx; i++) { if (nvws->pctx[i] == NULL) break; } if (i == nvws->nr_pctx) { nvws->nr_pctx++; nvws->pctx = realloc(nvws->pctx, sizeof(*nvws->pctx) * nvws->nr_pctx); } nvws->pctx[i] = init(pscreen, i); return nvws->pctx[i]; }
static void nvc0_so_target_save_offset(struct pipe_context *pipe, struct pipe_stream_output_target *ptarg, unsigned index, bool *serialize) { struct nvc0_so_target *targ = nvc0_so_target(ptarg); if (*serialize) { *serialize = false; PUSH_SPACE(nvc0_context(pipe)->base.pushbuf, 1); IMMED_NVC0(nvc0_context(pipe)->base.pushbuf, NVC0_3D(SERIALIZE), 0); NOUVEAU_DRV_STAT(nouveau_screen(pipe->screen), gpu_serialize_count, 1); } nvc0_query(targ->pq)->index = index; pipe->end_query(pipe, targ->pq); }
static void nouveau_buffer_destroy(struct pipe_screen *pscreen, struct pipe_resource *presource) { struct nv04_resource *res = nv04_resource(presource); nouveau_buffer_release_gpu_storage(res); if (res->data && !(res->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY)) align_free(res->data); nouveau_fence_ref(NULL, &res->fence); nouveau_fence_ref(NULL, &res->fence_wr); FREE(res); NOUVEAU_DRV_STAT(nouveau_screen(pscreen), buf_obj_current_count, -1); }
struct nouveau_bo * nouveau_screen_bo_from_handle(struct pipe_screen *pscreen, struct winsys_handle *whandle, unsigned *out_stride) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nouveau_bo *bo = 0; int ret; ret = nouveau_bo_handle_ref(dev, whandle->handle, &bo); if (ret) { debug_printf("%s: ref name 0x%08x failed with %d\n", __FUNCTION__, whandle->handle, ret); return NULL; } *out_stride = whandle->stride; return bo; }
static struct pipe_query * nv50_query_create(struct pipe_context *pipe, unsigned type) { struct nouveau_device *dev = nouveau_screen(pipe->screen)->device; struct nv50_query *q = CALLOC_STRUCT(nv50_query); int ret; assert (q->type == PIPE_QUERY_OCCLUSION_COUNTER); q->type = type; ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 256, 16, &q->bo); if (ret) { FREE(q); return NULL; } return (struct pipe_query *)q; }
/* Migrate data from glVertexAttribPointer(non-VBO) user buffers to GART. * We'd like to only allocate @size bytes here, but then we'd have to rebase * the vertex indices ... */ boolean nouveau_user_buffer_upload(struct nouveau_context *nv, struct nv04_resource *buf, unsigned base, unsigned size) { struct nouveau_screen *screen = nouveau_screen(buf->base.screen); int ret; assert(buf->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY); buf->base.width0 = base + size; if (!nouveau_buffer_reallocate(screen, buf, NOUVEAU_BO_GART)) return FALSE; ret = nouveau_bo_map(buf->bo, 0, nv->screen->client); if (ret) return FALSE; memcpy((uint8_t *)buf->bo->map + buf->offset + base, buf->data + base, size); return TRUE; }
/* Migrate data from glVertexAttribPointer(non-VBO) user buffers to GART. * We'd like to only allocate @size bytes here, but then we'd have to rebase * the vertex indices ... */ boolean nouveau_user_buffer_upload(struct nv04_resource *buf, unsigned base, unsigned size) { struct nouveau_screen *screen = nouveau_screen(buf->base.screen); int ret; assert(buf->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY); buf->base.width0 = base + size; if (!nouveau_buffer_reallocate(screen, buf, NOUVEAU_BO_GART)) return FALSE; ret = nouveau_bo_map_range(buf->bo, buf->offset + base, size, NOUVEAU_BO_WR | NOUVEAU_BO_NOSYNC); if (ret) return FALSE; memcpy(buf->bo->map, buf->data + base, size); nouveau_bo_unmap(buf->bo); return TRUE; }
static struct disk_cache * nouveau_screen_get_disk_shader_cache(struct pipe_screen *pscreen) { return nouveau_screen(pscreen)->disk_shader_cache; }
/* NOTE: ignoring line_last_pixel */ static void * nvc0_rasterizer_state_create(struct pipe_context *pipe, const struct pipe_rasterizer_state *cso) { struct nvc0_rasterizer_stateobj *so; uint16_t class_3d = nouveau_screen(pipe->screen)->class_3d; uint32_t reg; so = CALLOC_STRUCT(nvc0_rasterizer_stateobj); if (!so) return NULL; so->pipe = *cso; /* Scissor enables are handled in scissor state, we will not want to * always emit 16 commands, one for each scissor rectangle, here. */ SB_IMMED_3D(so, PROVOKING_VERTEX_LAST, !cso->flatshade_first); SB_IMMED_3D(so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside); SB_IMMED_3D(so, VERT_COLOR_CLAMP_EN, cso->clamp_vertex_color); SB_BEGIN_3D(so, FRAG_COLOR_CLAMP_EN, 1); SB_DATA (so, cso->clamp_fragment_color ? 0x11111111 : 0x00000000); SB_IMMED_3D(so, MULTISAMPLE_ENABLE, cso->multisample); SB_IMMED_3D(so, LINE_SMOOTH_ENABLE, cso->line_smooth); if (cso->line_smooth || cso->multisample) SB_BEGIN_3D(so, LINE_WIDTH_SMOOTH, 1); else SB_BEGIN_3D(so, LINE_WIDTH_ALIASED, 1); SB_DATA (so, fui(cso->line_width)); SB_IMMED_3D(so, LINE_STIPPLE_ENABLE, cso->line_stipple_enable); if (cso->line_stipple_enable) { SB_BEGIN_3D(so, LINE_STIPPLE_PATTERN, 1); SB_DATA (so, (cso->line_stipple_pattern << 8) | cso->line_stipple_factor); } SB_IMMED_3D(so, VP_POINT_SIZE, cso->point_size_per_vertex); if (!cso->point_size_per_vertex) { SB_BEGIN_3D(so, POINT_SIZE, 1); SB_DATA (so, fui(cso->point_size)); } reg = (cso->sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT) ? NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT : NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT; SB_BEGIN_3D(so, POINT_COORD_REPLACE, 1); SB_DATA (so, ((cso->sprite_coord_enable & 0xff) << 3) | reg); SB_IMMED_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization); SB_IMMED_3D(so, POINT_SMOOTH_ENABLE, cso->point_smooth); if (class_3d >= GM200_3D_CLASS) { SB_IMMED_3D(so, FILL_RECTANGLE, cso->fill_front == PIPE_POLYGON_MODE_FILL_RECTANGLE ? NVC0_3D_FILL_RECTANGLE_ENABLE : 0); } SB_BEGIN_3D(so, MACRO_POLYGON_MODE_FRONT, 1); SB_DATA (so, nvgl_polygon_mode(cso->fill_front)); SB_BEGIN_3D(so, MACRO_POLYGON_MODE_BACK, 1); SB_DATA (so, nvgl_polygon_mode(cso->fill_back)); SB_IMMED_3D(so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth); SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3); SB_DATA (so, cso->cull_face != PIPE_FACE_NONE); SB_DATA (so, cso->front_ccw ? NVC0_3D_FRONT_FACE_CCW : NVC0_3D_FRONT_FACE_CW); switch (cso->cull_face) { case PIPE_FACE_FRONT_AND_BACK: SB_DATA(so, NVC0_3D_CULL_FACE_FRONT_AND_BACK); break; case PIPE_FACE_FRONT: SB_DATA(so, NVC0_3D_CULL_FACE_FRONT); break; case PIPE_FACE_BACK: default: SB_DATA(so, NVC0_3D_CULL_FACE_BACK); break; } SB_IMMED_3D(so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable); SB_BEGIN_3D(so, POLYGON_OFFSET_POINT_ENABLE, 3); SB_DATA (so, cso->offset_point); SB_DATA (so, cso->offset_line); SB_DATA (so, cso->offset_tri); if (cso->offset_point || cso->offset_line || cso->offset_tri) { SB_BEGIN_3D(so, POLYGON_OFFSET_FACTOR, 1); SB_DATA (so, fui(cso->offset_scale)); if (!cso->offset_units_unscaled) { SB_BEGIN_3D(so, POLYGON_OFFSET_UNITS, 1); SB_DATA (so, fui(cso->offset_units * 2.0f)); } SB_BEGIN_3D(so, POLYGON_OFFSET_CLAMP, 1); SB_DATA (so, fui(cso->offset_clamp)); } if (cso->depth_clip) reg = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1; else reg = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1 | NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR | NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR | NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2; SB_BEGIN_3D(so, VIEW_VOLUME_CLIP_CTRL, 1); SB_DATA (so, reg); SB_IMMED_3D(so, DEPTH_CLIP_NEGATIVE_Z, cso->clip_halfz); SB_IMMED_3D(so, PIXEL_CENTER_INTEGER, !cso->half_pixel_center); assert(so->size <= ARRAY_SIZE(so->state)); return (void *)so; }
static int nvc0_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader, enum pipe_shader_cap param) { const uint16_t class_3d = nouveau_screen(pscreen)->class_3d; switch (shader) { case PIPE_SHADER_VERTEX: case PIPE_SHADER_GEOMETRY: case PIPE_SHADER_FRAGMENT: case PIPE_SHADER_COMPUTE: break; case PIPE_SHADER_TESS_CTRL: case PIPE_SHADER_TESS_EVAL: if (class_3d >= GM107_3D_CLASS) return 0; break; default: return 0; } switch (param) { case PIPE_SHADER_CAP_PREFERRED_IR: return PIPE_SHADER_IR_TGSI; case PIPE_SHADER_CAP_SUPPORTED_IRS: return 1 << PIPE_SHADER_IR_TGSI; case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: return 16384; case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: return 16; case PIPE_SHADER_CAP_MAX_INPUTS: if (shader == PIPE_SHADER_VERTEX) return 32; /* NOTE: These only count our slots for GENERIC varyings. * The address space may be larger, but the actual hard limit seems to be * less than what the address space layout permits, so don't add TEXCOORD, * COLOR, etc. here. */ if (shader == PIPE_SHADER_FRAGMENT) return 0x1f0 / 16; /* Actually this counts CLIPVERTEX, which occupies the last generic slot, * and excludes 0x60 per-patch inputs. */ return 0x200 / 16; case PIPE_SHADER_CAP_MAX_OUTPUTS: return 32; case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: return 65536; case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: return NVC0_MAX_PIPE_CONSTBUFS; case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: return shader != PIPE_SHADER_FRAGMENT; case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: return shader != PIPE_SHADER_FRAGMENT || class_3d < GM107_3D_CLASS; case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; case PIPE_SHADER_CAP_MAX_PREDS: return 0; case PIPE_SHADER_CAP_MAX_TEMPS: return NVC0_CAP_MAX_PROGRAM_TEMPS; case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: return 1; case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED: return 1; case PIPE_SHADER_CAP_SUBROUTINES: return 1; case PIPE_SHADER_CAP_INTEGERS: return 1; case PIPE_SHADER_CAP_DOUBLES: return 1; case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED: return 1; case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED: return 1; case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED: case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE: return 0; case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS: return NVC0_MAX_BUFFERS; case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: return 16; /* would be 32 in linked (OpenGL-style) mode */ case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS: return 16; /* XXX not sure if more are really safe */ case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT: return 32; case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: if (class_3d == NVE4_3D_CLASS || class_3d == NVF0_3D_CLASS) return NVC0_MAX_IMAGES; return 0; default: NOUVEAU_ERR("unknown PIPE_SHADER_CAP %d\n", param); return 0; } }
static int nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) { struct nv30_screen *screen = nv30_screen(pscreen); struct nouveau_object *eng3d = screen->eng3d; struct nouveau_device *dev = nouveau_screen(pscreen)->device; switch (param) { /* non-boolean capabilities */ case PIPE_CAP_MAX_RENDER_TARGETS: return (eng3d->oclass >= NV40_3D_CLASS) ? 4 : 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: return 13; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: return 10; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 13; case PIPE_CAP_GLSL_FEATURE_LEVEL: return 120; case PIPE_CAP_ENDIANNESS: return PIPE_ENDIAN_LITTLE; case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: return 16; case PIPE_CAP_MAX_VIEWPORTS: return 1; case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE: return 2048; /* supported capabilities */ case PIPE_CAP_TWO_SIDED_STENCIL: case PIPE_CAP_ANISOTROPIC_FILTER: case PIPE_CAP_POINT_SPRITE: case PIPE_CAP_OCCLUSION_QUERY: case PIPE_CAP_QUERY_TIME_ELAPSED: case PIPE_CAP_QUERY_TIMESTAMP: case PIPE_CAP_TEXTURE_SHADOW_MAP: case PIPE_CAP_TEXTURE_SWIZZLE: case PIPE_CAP_DEPTH_CLIP_DISABLE: case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: case PIPE_CAP_TGSI_TEXCOORD: case PIPE_CAP_USER_CONSTANT_BUFFERS: case PIPE_CAP_USER_INDEX_BUFFERS: case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: return 1; /* nv4x capabilities */ case PIPE_CAP_BLEND_EQUATION_SEPARATE: case PIPE_CAP_NPOT_TEXTURES: case PIPE_CAP_CONDITIONAL_RENDER: case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_PRIMITIVE_RESTART: return (eng3d->oclass >= NV40_3D_CLASS) ? 1 : 0; /* unsupported */ case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: case PIPE_CAP_SM3: case PIPE_CAP_INDEP_BLEND_ENABLE: case PIPE_CAP_INDEP_BLEND_FUNC: case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_TGSI_INSTANCEID: case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: /* XXX: yes? */ case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: case PIPE_CAP_MIN_TEXEL_OFFSET: case PIPE_CAP_MAX_TEXEL_OFFSET: case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET: case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET: case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES: case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS: case PIPE_CAP_MAX_VERTEX_STREAMS: case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: case PIPE_CAP_TEXTURE_BARRIER: case PIPE_CAP_SEAMLESS_CUBE_MAP: case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: case PIPE_CAP_CUBE_MAP_ARRAY: case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: case PIPE_CAP_VERTEX_COLOR_CLAMPED: case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: case PIPE_CAP_START_INSTANCE: case PIPE_CAP_TEXTURE_MULTISAMPLE: case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_QUERY_PIPELINE_STATISTICS: case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES: case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT: case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: case PIPE_CAP_TEXTURE_GATHER_SM5: case PIPE_CAP_RASTERIZER_LOWER_LEFT_ORIGIN: case PIPE_CAP_FAKE_SW_MSAA: case PIPE_CAP_TEXTURE_QUERY_LOD: case PIPE_CAP_SAMPLE_SHADING: case PIPE_CAP_TEXTURE_GATHER_OFFSETS: case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION: case PIPE_CAP_USER_VERTEX_BUFFERS: case PIPE_CAP_COMPUTE: case PIPE_CAP_DRAW_INDIRECT: case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE: case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: return 0; case PIPE_CAP_VENDOR_ID: return 0x10de; case PIPE_CAP_DEVICE_ID: { uint64_t device_id; if (nouveau_getparam(dev, NOUVEAU_GETPARAM_PCI_DEVICE, &device_id)) { NOUVEAU_ERR("NOUVEAU_GETPARAM_PCI_DEVICE failed.\n"); return -1; } return device_id; } case PIPE_CAP_ACCELERATED: return 1; case PIPE_CAP_VIDEO_MEMORY: return dev->vram_size >> 20; case PIPE_CAP_UMA: return 0; } debug_printf("unknown param %d\n", param); return 0; }
struct pipe_resource * nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *tmpl) { struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv30_miptree *mt = CALLOC_STRUCT(nv30_miptree); struct pipe_resource *pt = &mt->base.base; unsigned blocksz, size; unsigned w, h, d, l; int ret; switch (tmpl->nr_samples) { case 4: mt->ms_mode = 0x00004000; mt->ms_x = 1; mt->ms_y = 1; break; case 2: mt->ms_mode = 0x00003000; mt->ms_x = 1; mt->ms_y = 0; break; default: mt->ms_mode = 0x00000000; mt->ms_x = 0; mt->ms_y = 0; break; } mt->base.vtbl = &nv30_miptree_vtbl; *pt = *tmpl; pipe_reference_init(&pt->reference, 1); pt->screen = pscreen; w = pt->width0 << mt->ms_x; h = pt->height0 << mt->ms_y; d = (pt->target == PIPE_TEXTURE_3D) ? pt->depth0 : 1; blocksz = util_format_get_blocksize(pt->format); if ((pt->target == PIPE_TEXTURE_RECT) || !util_is_power_of_two(pt->width0) || !util_is_power_of_two(pt->height0) || !util_is_power_of_two(pt->depth0) || util_format_is_compressed(pt->format) || util_format_is_float(pt->format) || mt->ms_mode) { mt->uniform_pitch = util_format_get_nblocksx(pt->format, w) * blocksz; mt->uniform_pitch = align(mt->uniform_pitch, 64); } if (!mt->uniform_pitch) mt->swizzled = TRUE; size = 0; for (l = 0; l <= pt->last_level; l++) { struct nv30_miptree_level *lvl = &mt->level[l]; unsigned nbx = util_format_get_nblocksx(pt->format, w); unsigned nby = util_format_get_nblocksx(pt->format, h); lvl->offset = size; lvl->pitch = mt->uniform_pitch; if (!lvl->pitch) lvl->pitch = nbx * blocksz; lvl->zslice_size = lvl->pitch * nby; size += lvl->zslice_size * d; w = u_minify(w, 1); h = u_minify(h, 1); d = u_minify(d, 1); } mt->layer_size = size; if (pt->target == PIPE_TEXTURE_CUBE) { if (!mt->uniform_pitch) mt->layer_size = align(mt->layer_size, 128); size = mt->layer_size * 6; } ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 256, size, NULL, &mt->base.bo); if (ret) { FREE(mt); return NULL; } mt->base.domain = NOUVEAU_BO_VRAM; return &mt->base.base; }
static int nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) { const uint16_t class_3d = nouveau_screen(pscreen)->class_3d; struct nouveau_device *dev = nouveau_screen(pscreen)->device; switch (param) { /* non-boolean caps */ case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: return 14; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: return 12; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 14; case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: return 512; case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET: case PIPE_CAP_MIN_TEXEL_OFFSET: return -8; case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET: case PIPE_CAP_MAX_TEXEL_OFFSET: return 7; case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: return 128 * 1024 * 1024; case PIPE_CAP_GLSL_FEATURE_LEVEL: return 330; case PIPE_CAP_MAX_RENDER_TARGETS: return 8; case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: return 1; case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: return 4; case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: return 64; case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES: case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS: return 1024; case PIPE_CAP_MAX_VERTEX_STREAMS: return 1; case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE: return 2048; case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: return 256; case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: return 1; /* 256 for binding as RT, but that's not possible in GL */ case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: return NOUVEAU_MIN_BUFFER_MAP_ALIGN; case PIPE_CAP_MAX_VIEWPORTS: return NV50_MAX_VIEWPORTS; case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50; case PIPE_CAP_ENDIANNESS: return PIPE_ENDIAN_LITTLE; case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: return (class_3d >= NVA3_3D_CLASS) ? 4 : 0; /* supported caps */ case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_TEXTURE_SWIZZLE: case PIPE_CAP_TEXTURE_SHADOW_MAP: case PIPE_CAP_NPOT_TEXTURES: case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES: case PIPE_CAP_ANISOTROPIC_FILTER: case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: case PIPE_CAP_TWO_SIDED_STENCIL: case PIPE_CAP_DEPTH_CLIP_DISABLE: case PIPE_CAP_POINT_SPRITE: case PIPE_CAP_SM3: case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: case PIPE_CAP_VERTEX_COLOR_CLAMPED: case PIPE_CAP_QUERY_TIMESTAMP: case PIPE_CAP_QUERY_TIME_ELAPSED: case PIPE_CAP_OCCLUSION_QUERY: case PIPE_CAP_BLEND_EQUATION_SEPARATE: case PIPE_CAP_INDEP_BLEND_ENABLE: case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: case PIPE_CAP_PRIMITIVE_RESTART: case PIPE_CAP_TGSI_INSTANCEID: case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: case PIPE_CAP_CONDITIONAL_RENDER: case PIPE_CAP_TEXTURE_BARRIER: case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: case PIPE_CAP_START_INSTANCE: case PIPE_CAP_USER_CONSTANT_BUFFERS: case PIPE_CAP_USER_INDEX_BUFFERS: case PIPE_CAP_USER_VERTEX_BUFFERS: case PIPE_CAP_TEXTURE_MULTISAMPLE: case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE: case PIPE_CAP_SAMPLER_VIEW_TARGET: case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: case PIPE_CAP_CLIP_HALFZ: case PIPE_CAP_POLYGON_OFFSET_CLAMP: case PIPE_CAP_QUERY_PIPELINE_STATISTICS: case PIPE_CAP_TEXTURE_FLOAT_LINEAR: case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR: case PIPE_CAP_DEPTH_BOUNDS_TEST: case PIPE_CAP_TGSI_TXQS: case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS: case PIPE_CAP_SHAREABLE_SHADERS: case PIPE_CAP_CLEAR_TEXTURE: case PIPE_CAP_COMPUTE: case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: return 1; case PIPE_CAP_SEAMLESS_CUBE_MAP: return 1; /* class_3d >= NVA0_3D_CLASS; */ /* supported on nva0+ */ case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: return class_3d >= NVA0_3D_CLASS; /* supported on nva3+ */ case PIPE_CAP_CUBE_MAP_ARRAY: case PIPE_CAP_INDEP_BLEND_FUNC: case PIPE_CAP_TEXTURE_QUERY_LOD: case PIPE_CAP_SAMPLE_SHADING: case PIPE_CAP_FORCE_PERSAMPLE_INTERP: return class_3d >= NVA3_3D_CLASS; /* unsupported caps */ case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_TGSI_TEXCOORD: case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT: case PIPE_CAP_TEXTURE_GATHER_SM5: case PIPE_CAP_FAKE_SW_MSAA: case PIPE_CAP_TEXTURE_GATHER_OFFSETS: case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION: case PIPE_CAP_DRAW_INDIRECT: case PIPE_CAP_MULTI_DRAW_INDIRECT: case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS: case PIPE_CAP_VERTEXID_NOBASE: case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: /* potentially supported on some hw */ case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS: case PIPE_CAP_DRAW_PARAMETERS: case PIPE_CAP_TGSI_PACK_HALF_FLOAT: case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: case PIPE_CAP_GENERATE_MIPMAP: case PIPE_CAP_STRING_MARKER: case PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY: case PIPE_CAP_SURFACE_REINTERPRET_BLOCKS: case PIPE_CAP_QUERY_BUFFER_OBJECT: case PIPE_CAP_QUERY_MEMORY_INFO: return 0; case PIPE_CAP_VENDOR_ID: return 0x10de; case PIPE_CAP_DEVICE_ID: { uint64_t device_id; if (nouveau_getparam(dev, NOUVEAU_GETPARAM_PCI_DEVICE, &device_id)) { NOUVEAU_ERR("NOUVEAU_GETPARAM_PCI_DEVICE failed.\n"); return -1; } return device_id; } case PIPE_CAP_ACCELERATED: return 1; case PIPE_CAP_VIDEO_MEMORY: return dev->vram_size >> 20; case PIPE_CAP_UMA: return 0; } NOUVEAU_ERR("unknown PIPE_CAP %d\n", param); return 0; }
void nvc0_m2mf_transfer_rect(struct pipe_screen *pscreen, const struct nv50_m2mf_rect *dst, const struct nv50_m2mf_rect *src, uint32_t nblocksx, uint32_t nblocksy) { struct nouveau_channel *chan = nouveau_screen(pscreen)->channel; const int cpp = dst->cpp; uint32_t src_ofst = src->base; uint32_t dst_ofst = dst->base; uint32_t height = nblocksy; uint32_t sy = src->y; uint32_t dy = dst->y; uint32_t exec = (1 << 20); assert(dst->cpp == src->cpp); if (nouveau_bo_tile_layout(src->bo)) { BEGIN_RING(chan, RING_MF(TILING_MODE_IN), 5); OUT_RING (chan, src->tile_mode); OUT_RING (chan, src->width * cpp); OUT_RING (chan, src->height); OUT_RING (chan, src->depth); OUT_RING (chan, src->z); } else { src_ofst += src->y * src->pitch + src->x * cpp; BEGIN_RING(chan, RING_MF(PITCH_IN), 1); OUT_RING (chan, src->width * cpp); exec |= NVC0_M2MF_EXEC_LINEAR_IN; } if (nouveau_bo_tile_layout(dst->bo)) { BEGIN_RING(chan, RING_MF(TILING_MODE_OUT), 5); OUT_RING (chan, dst->tile_mode); OUT_RING (chan, dst->width * cpp); OUT_RING (chan, dst->height); OUT_RING (chan, dst->depth); OUT_RING (chan, dst->z); } else { dst_ofst += dst->y * dst->pitch + dst->x * cpp; BEGIN_RING(chan, RING_MF(PITCH_OUT), 1); OUT_RING (chan, dst->width * cpp); exec |= NVC0_M2MF_EXEC_LINEAR_OUT; } while (height) { int line_count = height > 2047 ? 2047 : height; MARK_RING (chan, 17, 4); BEGIN_RING(chan, RING_MF(OFFSET_IN_HIGH), 2); OUT_RELOCh(chan, src->bo, src_ofst, src->domain | NOUVEAU_BO_RD); OUT_RELOCl(chan, src->bo, src_ofst, src->domain | NOUVEAU_BO_RD); BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2); OUT_RELOCh(chan, dst->bo, dst_ofst, dst->domain | NOUVEAU_BO_WR); OUT_RELOCl(chan, dst->bo, dst_ofst, dst->domain | NOUVEAU_BO_WR); if (!(exec & NVC0_M2MF_EXEC_LINEAR_IN)) { BEGIN_RING(chan, RING_MF(TILING_POSITION_IN_X), 2); OUT_RING (chan, src->x * cpp); OUT_RING (chan, sy); } else { src_ofst += line_count * src->pitch; } if (!(exec & NVC0_M2MF_EXEC_LINEAR_OUT)) { BEGIN_RING(chan, RING_MF(TILING_POSITION_OUT_X), 2); OUT_RING (chan, dst->x * cpp); OUT_RING (chan, dy); } else { dst_ofst += line_count * dst->pitch; } BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2); OUT_RING (chan, nblocksx * cpp); OUT_RING (chan, line_count); BEGIN_RING(chan, RING_MF(EXEC), 1); OUT_RING (chan, exec); height -= line_count; sy += line_count; dy += line_count; } }
void * nv50_sampler_state_create(struct pipe_context *pipe, const struct pipe_sampler_state *cso) { struct nv50_tsc_entry *so = MALLOC_STRUCT(nv50_tsc_entry); float f[2]; so->id = -1; so->tsc[0] = (0x00026000 | (nv50_tsc_wrap_mode(cso->wrap_s) << 0) | (nv50_tsc_wrap_mode(cso->wrap_t) << 3) | (nv50_tsc_wrap_mode(cso->wrap_r) << 6)); switch (cso->mag_img_filter) { case PIPE_TEX_FILTER_LINEAR: so->tsc[1] = NV50_TSC_1_MAGF_LINEAR; break; case PIPE_TEX_FILTER_NEAREST: default: so->tsc[1] = NV50_TSC_1_MAGF_NEAREST; break; } switch (cso->min_img_filter) { case PIPE_TEX_FILTER_LINEAR: so->tsc[1] |= NV50_TSC_1_MINF_LINEAR; break; case PIPE_TEX_FILTER_NEAREST: default: so->tsc[1] |= NV50_TSC_1_MINF_NEAREST; break; } switch (cso->min_mip_filter) { case PIPE_TEX_MIPFILTER_LINEAR: so->tsc[1] |= NV50_TSC_1_MIPF_LINEAR; break; case PIPE_TEX_MIPFILTER_NEAREST: so->tsc[1] |= NV50_TSC_1_MIPF_NEAREST; break; case PIPE_TEX_MIPFILTER_NONE: default: so->tsc[1] |= NV50_TSC_1_MIPF_NONE; break; } if (nouveau_screen(pipe->screen)->class_3d >= NVE4_3D_CLASS) { if (cso->seamless_cube_map) so->tsc[1] |= NVE4_TSC_1_CUBE_SEAMLESS; if (!cso->normalized_coords) so->tsc[1] |= NVE4_TSC_1_FORCE_NONNORMALIZED_COORDS; } if (cso->max_anisotropy >= 16) so->tsc[0] |= (7 << 20); else if (cso->max_anisotropy >= 12) so->tsc[0] |= (6 << 20); else { so->tsc[0] |= (cso->max_anisotropy >> 1) << 20; if (cso->max_anisotropy >= 4) so->tsc[1] |= NV50_TSC_1_UNKN_ANISO_35; else if (cso->max_anisotropy >= 2) so->tsc[1] |= NV50_TSC_1_UNKN_ANISO_15; } if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { /* NOTE: must be deactivated for non-shadow textures */ so->tsc[0] |= (1 << 9); so->tsc[0] |= (nvgl_comparison_op(cso->compare_func) & 0x7) << 10; } f[0] = CLAMP(cso->lod_bias, -16.0f, 15.0f); so->tsc[1] |= ((int)(f[0] * 256.0f) & 0x1fff) << 12; f[0] = CLAMP(cso->min_lod, 0.0f, 15.0f); f[1] = CLAMP(cso->max_lod, 0.0f, 15.0f); so->tsc[2] = (((int)(f[1] * 256.0f) & 0xfff) << 12) | ((int)(f[0] * 256.0f) & 0xfff); so->tsc[2] |= util_format_linear_float_to_srgb_8unorm(cso->border_color.f[0]) << 24; so->tsc[3] = util_format_linear_float_to_srgb_8unorm(cso->border_color.f[1]) << 12; so->tsc[3] |= util_format_linear_float_to_srgb_8unorm(cso->border_color.f[2]) << 20; so->tsc[4] = fui(cso->border_color.f[0]); so->tsc[5] = fui(cso->border_color.f[1]); so->tsc[6] = fui(cso->border_color.f[2]); so->tsc[7] = fui(cso->border_color.f[3]); return (void *)so; }
static int nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) { const uint16_t class_3d = nouveau_screen(pscreen)->class_3d; switch (param) { case PIPE_CAP_MAX_COMBINED_SAMPLERS: return 64; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: return 14; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: return 12; case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 14; case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: return 512; case PIPE_CAP_MIN_TEXEL_OFFSET: return -8; case PIPE_CAP_MAX_TEXEL_OFFSET: return 7; case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_TEXTURE_SWIZZLE: case PIPE_CAP_TEXTURE_SHADOW_MAP: case PIPE_CAP_NPOT_TEXTURES: case PIPE_CAP_ANISOTROPIC_FILTER: case PIPE_CAP_SCALED_RESOLVE: case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: return 1; case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: return 65536; case PIPE_CAP_SEAMLESS_CUBE_MAP: return nv50_screen(pscreen)->tesla->oclass >= NVA0_3D_CLASS; case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: return 0; case PIPE_CAP_CUBE_MAP_ARRAY: return 0; /* return nv50_screen(pscreen)->tesla->oclass >= NVA3_3D_CLASS; */ case PIPE_CAP_TWO_SIDED_STENCIL: case PIPE_CAP_DEPTH_CLIP_DISABLE: case PIPE_CAP_POINT_SPRITE: return 1; case PIPE_CAP_SM3: return 1; case PIPE_CAP_GLSL_FEATURE_LEVEL: return 140; case PIPE_CAP_MAX_RENDER_TARGETS: return 8; case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: return 1; case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: case PIPE_CAP_VERTEX_COLOR_CLAMPED: return 1; case PIPE_CAP_QUERY_TIMESTAMP: case PIPE_CAP_QUERY_TIME_ELAPSED: case PIPE_CAP_OCCLUSION_QUERY: return 1; case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: return 4; case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: return 64; case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: return (class_3d >= NVA0_3D_CLASS) ? 1 : 0; case PIPE_CAP_BLEND_EQUATION_SEPARATE: case PIPE_CAP_INDEP_BLEND_ENABLE: return 1; case PIPE_CAP_INDEP_BLEND_FUNC: return nv50_screen(pscreen)->tesla->oclass >= NVA3_3D_CLASS; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return 1; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return 0; case PIPE_CAP_SHADER_STENCIL_EXPORT: return 0; case PIPE_CAP_PRIMITIVE_RESTART: case PIPE_CAP_TGSI_INSTANCEID: case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: case PIPE_CAP_CONDITIONAL_RENDER: case PIPE_CAP_TEXTURE_BARRIER: case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: case PIPE_CAP_START_INSTANCE: return 1; case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: return 0; /* state trackers will know better */ case PIPE_CAP_USER_CONSTANT_BUFFERS: case PIPE_CAP_USER_INDEX_BUFFERS: case PIPE_CAP_USER_VERTEX_BUFFERS: return 1; case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: return 256; case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: return 1; /* 256 for binding as RT, but that's not possible in GL */ case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: return NOUVEAU_MIN_BUFFER_MAP_ALIGN; case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_TGSI_TEXCOORD: case PIPE_CAP_TEXTURE_MULTISAMPLE: return 0; case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: return 1; case PIPE_CAP_QUERY_PIPELINE_STATISTICS: return 0; case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50; case PIPE_CAP_ENDIANNESS: return PIPE_ENDIAN_LITTLE; default: NOUVEAU_ERR("unknown PIPE_CAP %d\n", param); return 0; } }