void ASPSYoungGen::resize_spaces(size_t requested_eden_size, size_t requested_survivor_size) { assert(UseAdaptiveSizePolicy, "sanity check"); assert(requested_eden_size > 0 && requested_survivor_size > 0, "just checking"); space_invariants(); // We require eden and to space to be empty if ((!eden_space()->is_empty()) || (!to_space()->is_empty())) { return; } if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr("PSYoungGen::resize_spaces(requested_eden_size: " SIZE_FORMAT ", requested_survivor_size: " SIZE_FORMAT ")", requested_eden_size, requested_survivor_size); gclog_or_tty->print_cr(" eden: [" PTR_FORMAT ".." PTR_FORMAT ") " SIZE_FORMAT, eden_space()->bottom(), eden_space()->end(), pointer_delta(eden_space()->end(), eden_space()->bottom(), sizeof(char))); gclog_or_tty->print_cr(" from: [" PTR_FORMAT ".." PTR_FORMAT ") " SIZE_FORMAT, from_space()->bottom(), from_space()->end(), pointer_delta(from_space()->end(), from_space()->bottom(), sizeof(char))); gclog_or_tty->print_cr(" to: [" PTR_FORMAT ".." PTR_FORMAT ") " SIZE_FORMAT, to_space()->bottom(), to_space()->end(), pointer_delta( to_space()->end(), to_space()->bottom(), sizeof(char))); } // There's nothing to do if the new sizes are the same as the current if (requested_survivor_size == to_space()->capacity_in_bytes() && requested_survivor_size == from_space()->capacity_in_bytes() && requested_eden_size == eden_space()->capacity_in_bytes()) { if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" capacities are the right sizes, returning"); } return; } char* eden_start = (char*)virtual_space()->low(); char* eden_end = (char*)eden_space()->end(); char* from_start = (char*)from_space()->bottom(); char* from_end = (char*)from_space()->end(); char* to_start = (char*)to_space()->bottom(); char* to_end = (char*)to_space()->end(); assert(eden_start < from_start, "Cannot push into from_space"); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); const size_t alignment = heap->intra_heap_alignment(); const bool maintain_minimum = (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size(); bool eden_from_to_order = from_start < to_start; // Check whether from space is below to space if (eden_from_to_order) { // Eden, from, to if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" Eden, from, to:"); } // Set eden // "requested_eden_size" is a goal for the size of eden // and may not be attainable. "eden_size" below is // calculated based on the location of from-space and // the goal for the size of eden. from-space is // fixed in place because it contains live data. // The calculation is done this way to avoid 32bit // overflow (i.e., eden_start + requested_eden_size // may too large for representation in 32bits). size_t eden_size; if (maintain_minimum) { // Only make eden larger than the requested size if // the minimum size of the generation has to be maintained. // This could be done in general but policy at a higher // level is determining a requested size for eden and that // should be honored unless there is a fundamental reason. eden_size = pointer_delta(from_start, eden_start, sizeof(char)); } else { eden_size = MIN2(requested_eden_size, pointer_delta(from_start, eden_start, sizeof(char))); } eden_end = eden_start + eden_size; assert(eden_end >= eden_start, "addition overflowed") // To may resize into from space as long as it is clear of live data. // From space must remain page aligned, though, so we need to do some // extra calculations. // First calculate an optimal to-space to_end = (char*)virtual_space()->high(); to_start = (char*)pointer_delta(to_end, (char*)requested_survivor_size, sizeof(char)); // Does the optimal to-space overlap from-space? if (to_start < (char*)from_space()->end()) { assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity"); // Calculate the minimum offset possible for from_end size_t from_size = pointer_delta(from_space()->top(), from_start, sizeof(char)); // Should we be in this method if from_space is empty? Why not the set_space method? FIX ME! if (from_size == 0) { from_size = alignment; } else { from_size = align_size_up(from_size, alignment); } from_end = from_start + from_size; assert(from_end > from_start, "addition overflow or from_size problem"); guarantee(from_end <= (char*)from_space()->end(), "from_end moved to the right"); // Now update to_start with the new from_end to_start = MAX2(from_end, to_start); } guarantee(to_start != to_end, "to space is zero sized"); if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" [eden_start .. eden_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, eden_start, eden_end, pointer_delta(eden_end, eden_start, sizeof(char))); gclog_or_tty->print_cr(" [from_start .. from_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, from_start, from_end, pointer_delta(from_end, from_start, sizeof(char))); gclog_or_tty->print_cr(" [ to_start .. to_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, to_start, to_end, pointer_delta( to_end, to_start, sizeof(char))); } } else { // Eden, to, from if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" Eden, to, from:"); } // To space gets priority over eden resizing. Note that we position // to space as if we were able to resize from space, even though from // space is not modified. // Giving eden priority was tried and gave poorer performance. to_end = (char*)pointer_delta(virtual_space()->high(), (char*)requested_survivor_size, sizeof(char)); to_end = MIN2(to_end, from_start); to_start = (char*)pointer_delta(to_end, (char*)requested_survivor_size, sizeof(char)); // if the space sizes are to be increased by several times then // 'to_start' will point beyond the young generation. In this case // 'to_start' should be adjusted. to_start = MAX2(to_start, eden_start + alignment); // Compute how big eden can be, then adjust end. // See comments above on calculating eden_end. size_t eden_size; if (maintain_minimum) { eden_size = pointer_delta(to_start, eden_start, sizeof(char)); } else { eden_size = MIN2(requested_eden_size, pointer_delta(to_start, eden_start, sizeof(char))); } eden_end = eden_start + eden_size; assert(eden_end >= eden_start, "addition overflowed") // Don't let eden shrink down to 0 or less. eden_end = MAX2(eden_end, eden_start + alignment); to_start = MAX2(to_start, eden_end); if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" [eden_start .. eden_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, eden_start, eden_end, pointer_delta(eden_end, eden_start, sizeof(char))); gclog_or_tty->print_cr(" [ to_start .. to_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, to_start, to_end, pointer_delta( to_end, to_start, sizeof(char))); gclog_or_tty->print_cr(" [from_start .. from_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, from_start, from_end, pointer_delta(from_end, from_start, sizeof(char))); } } guarantee((HeapWord*)from_start <= from_space()->bottom(), "from start moved to the right"); guarantee((HeapWord*)from_end >= from_space()->top(), "from end moved into live data"); assert(is_object_aligned((intptr_t)eden_start), "checking alignment"); assert(is_object_aligned((intptr_t)from_start), "checking alignment"); assert(is_object_aligned((intptr_t)to_start), "checking alignment"); MemRegion edenMR((HeapWord*)eden_start, (HeapWord*)eden_end); MemRegion toMR ((HeapWord*)to_start, (HeapWord*)to_end); MemRegion fromMR((HeapWord*)from_start, (HeapWord*)from_end); // Let's make sure the call to initialize doesn't reset "top"! DEBUG_ONLY(HeapWord* old_from_top = from_space()->top();)
static int update_tss_binding(struct svga_context *svga, unsigned dirty ) { unsigned i; unsigned count = MAX2( svga->curr.num_textures, svga->state.hw_draw.num_views ); unsigned min_lod; unsigned max_lod; struct { struct { unsigned unit; struct svga_hw_view_state *view; } bind[PIPE_MAX_SAMPLERS]; unsigned bind_count; } queue; queue.bind_count = 0; for (i = 0; i < count; i++) { const struct svga_sampler_state *s = svga->curr.sampler[i]; struct svga_hw_view_state *view = &svga->state.hw_draw.views[i]; /* get min max lod */ if (svga->curr.texture[i]) { min_lod = MAX2(s->view_min_lod, 0); max_lod = MIN2(s->view_max_lod, svga->curr.texture[i]->last_level); } else { min_lod = 0; max_lod = 0; } if (view->texture != svga->curr.texture[i] || view->min_lod != min_lod || view->max_lod != max_lod) { svga_sampler_view_reference(&view->v, NULL); pipe_texture_reference( &view->texture, svga->curr.texture[i] ); view->dirty = TRUE; view->min_lod = min_lod; view->max_lod = max_lod; if (svga->curr.texture[i]) view->v = svga_get_tex_sampler_view(&svga->pipe, svga->curr.texture[i], min_lod, max_lod); } if (view->dirty) { queue.bind[queue.bind_count].unit = i; queue.bind[queue.bind_count].view = view; queue.bind_count++; } else if (view->v) { svga_validate_sampler_view(svga, view->v); } } svga->state.hw_draw.num_views = svga->curr.num_textures; if (queue.bind_count) { SVGA3dTextureState *ts; if (SVGA3D_BeginSetTextureState( svga->swc, &ts, queue.bind_count ) != PIPE_OK) goto fail; for (i = 0; i < queue.bind_count; i++) { ts[i].stage = queue.bind[i].unit; ts[i].name = SVGA3D_TS_BIND_TEXTURE; if (queue.bind[i].view->v) { svga->swc->surface_relocation(svga->swc, &ts[i].value, queue.bind[i].view->v->handle, PIPE_BUFFER_USAGE_GPU_READ); } else { ts[i].value = SVGA3D_INVALID_ID; } queue.bind[i].view->dirty = FALSE; } SVGA_FIFOCommitAll( svga->swc ); } return 0; fail: return PIPE_ERROR_OUT_OF_MEMORY; }
/* Create the device specific context. */ GLboolean r100CreateContext( gl_api api, const struct gl_config *glVisual, __DRIcontext *driContextPriv, unsigned major_version, unsigned minor_version, uint32_t flags, unsigned *error, void *sharedContextPrivate) { __DRIscreen *sPriv = driContextPriv->driScreenPriv; radeonScreenPtr screen = (radeonScreenPtr)(sPriv->driverPrivate); struct dd_function_table functions; r100ContextPtr rmesa; struct gl_context *ctx; int i; int tcl_mode, fthrottle_mode; /* API and flag filtering is handled in dri2CreateContextAttribs. */ (void) api; (void) flags; assert(glVisual); assert(driContextPriv); assert(screen); /* Allocate the Radeon context */ rmesa = (r100ContextPtr) CALLOC( sizeof(*rmesa) ); if ( !rmesa ) { *error = __DRI_CTX_ERROR_NO_MEMORY; return GL_FALSE; } rmesa->radeon.radeonScreen = screen; r100_init_vtbl(&rmesa->radeon); /* init exp fog table data */ radeonInitStaticFogData(); /* Parse configuration files. * Do this here so that initialMaxAnisotropy is set before we create * the default textures. */ driParseConfigFiles (&rmesa->radeon.optionCache, &screen->optionCache, screen->driScreen->myNum, "radeon"); rmesa->radeon.initialMaxAnisotropy = driQueryOptionf(&rmesa->radeon.optionCache, "def_max_anisotropy"); if ( driQueryOptionb( &rmesa->radeon.optionCache, "hyperz" ) ) { if ( sPriv->drm_version.minor < 13 ) fprintf( stderr, "DRM version 1.%d too old to support HyperZ, " "disabling.\n", sPriv->drm_version.minor ); else rmesa->using_hyperz = GL_TRUE; } if ( sPriv->drm_version.minor >= 15 ) rmesa->texmicrotile = GL_TRUE; /* Init default driver functions then plug in our Radeon-specific functions * (the texture functions are especially important) */ _mesa_init_driver_functions( &functions ); radeonInitTextureFuncs( &rmesa->radeon, &functions ); radeonInitQueryObjFunctions(&functions); if (!radeonInitContext(&rmesa->radeon, &functions, glVisual, driContextPriv, sharedContextPrivate)) { FREE(rmesa); *error = __DRI_CTX_ERROR_NO_MEMORY; return GL_FALSE; } rmesa->radeon.swtcl.RenderIndex = ~0; rmesa->radeon.hw.all_dirty = GL_TRUE; /* Set the maximum texture size small enough that we can guarentee that * all texture units can bind a maximal texture and have all of them in * texturable memory at once. Depending on the allow_large_textures driconf * setting allow larger textures. */ ctx = rmesa->radeon.glCtx; ctx->Const.MaxTextureUnits = driQueryOptioni (&rmesa->radeon.optionCache, "texture_units"); ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits; ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits; ctx->Const.MaxCombinedTextureImageUnits = ctx->Const.MaxTextureUnits; ctx->Const.StripTextureBorder = GL_TRUE; i = driQueryOptioni( &rmesa->radeon.optionCache, "allow_large_textures"); /* FIXME: When no memory manager is available we should set this * to some reasonable value based on texture memory pool size */ ctx->Const.MaxTextureLevels = 12; ctx->Const.Max3DTextureLevels = 9; ctx->Const.MaxCubeTextureLevels = 12; ctx->Const.MaxTextureRectSize = 2048; ctx->Const.MaxTextureMaxAnisotropy = 16.0; /* No wide points. */ ctx->Const.MinPointSize = 1.0; ctx->Const.MinPointSizeAA = 1.0; ctx->Const.MaxPointSize = 1.0; ctx->Const.MaxPointSizeAA = 1.0; ctx->Const.MinLineWidth = 1.0; ctx->Const.MinLineWidthAA = 1.0; ctx->Const.MaxLineWidth = 10.0; ctx->Const.MaxLineWidthAA = 10.0; ctx->Const.LineWidthGranularity = 0.0625; /* Set maxlocksize (and hence vb size) small enough to avoid * fallbacks in radeon_tcl.c. ie. guarentee that all vertices can * fit in a single dma buffer for indexed rendering of quad strips, * etc. */ ctx->Const.MaxArrayLockSize = MIN2( ctx->Const.MaxArrayLockSize, RADEON_BUFFER_SIZE / RADEON_MAX_TCL_VERTSIZE ); rmesa->boxes = 0; ctx->Const.MaxDrawBuffers = 1; ctx->Const.MaxColorAttachments = 1; ctx->Const.MaxRenderbufferSize = 2048; _mesa_set_mvp_with_dp4( ctx, GL_TRUE ); /* Initialize the software rasterizer and helper modules. */ _swrast_CreateContext( ctx ); _vbo_CreateContext( ctx ); _tnl_CreateContext( ctx ); _swsetup_CreateContext( ctx ); _ae_create_context( ctx ); /* Install the customized pipeline: */ _tnl_destroy_pipeline( ctx ); _tnl_install_pipeline( ctx, radeon_pipeline ); /* Try and keep materials and vertices separate: */ /* _tnl_isolate_materials( ctx, GL_TRUE ); */ /* Configure swrast and T&L to match hardware characteristics: */ _swrast_allow_pixel_fog( ctx, GL_FALSE ); _swrast_allow_vertex_fog( ctx, GL_TRUE ); _tnl_allow_pixel_fog( ctx, GL_FALSE ); _tnl_allow_vertex_fog( ctx, GL_TRUE ); for ( i = 0 ; i < RADEON_MAX_TEXTURE_UNITS ; i++ ) { _math_matrix_ctr( &rmesa->TexGenMatrix[i] ); _math_matrix_ctr( &rmesa->tmpmat[i] ); _math_matrix_set_identity( &rmesa->TexGenMatrix[i] ); _math_matrix_set_identity( &rmesa->tmpmat[i] ); } ctx->Extensions.ARB_texture_border_clamp = true; ctx->Extensions.ARB_texture_env_combine = true; ctx->Extensions.ARB_texture_env_crossbar = true; ctx->Extensions.ARB_texture_env_dot3 = true; ctx->Extensions.EXT_fog_coord = true; ctx->Extensions.EXT_packed_depth_stencil = true; ctx->Extensions.EXT_secondary_color = true; ctx->Extensions.EXT_texture_env_dot3 = true; ctx->Extensions.EXT_texture_filter_anisotropic = true; ctx->Extensions.EXT_texture_mirror_clamp = true; ctx->Extensions.ATI_texture_env_combine3 = true; ctx->Extensions.ATI_texture_mirror_once = true; ctx->Extensions.MESA_ycbcr_texture = true; ctx->Extensions.NV_blend_square = true; #if FEATURE_OES_EGL_image ctx->Extensions.OES_EGL_image = true; #endif ctx->Extensions.EXT_framebuffer_object = true; ctx->Extensions.ARB_texture_cube_map = true; if (rmesa->radeon.glCtx->Mesa_DXTn) { ctx->Extensions.EXT_texture_compression_s3tc = true; ctx->Extensions.S3_s3tc = true; } else if (driQueryOptionb (&rmesa->radeon.optionCache, "force_s3tc_enable")) { ctx->Extensions.EXT_texture_compression_s3tc = true; } ctx->Extensions.NV_texture_rectangle = true; ctx->Extensions.ARB_occlusion_query = true; /* XXX these should really go right after _mesa_init_driver_functions() */ radeon_fbo_init(&rmesa->radeon); radeonInitSpanFuncs( ctx ); radeonInitIoctlFuncs( ctx ); radeonInitStateFuncs( ctx ); radeonInitState( rmesa ); radeonInitSwtcl( ctx ); _mesa_vector4f_alloc( &rmesa->tcl.ObjClean, 0, ctx->Const.MaxArrayLockSize, 32 ); fthrottle_mode = driQueryOptioni(&rmesa->radeon.optionCache, "fthrottle_mode"); rmesa->radeon.iw.irq_seq = -1; rmesa->radeon.irqsEmitted = 0; rmesa->radeon.do_irqs = (rmesa->radeon.radeonScreen->irq != 0 && fthrottle_mode == DRI_CONF_FTHROTTLE_IRQS); rmesa->radeon.do_usleeps = (fthrottle_mode == DRI_CONF_FTHROTTLE_USLEEPS); #if DO_DEBUG RADEON_DEBUG = driParseDebugString( getenv( "RADEON_DEBUG" ), debug_control ); #endif tcl_mode = driQueryOptioni(&rmesa->radeon.optionCache, "tcl_mode"); if (driQueryOptionb(&rmesa->radeon.optionCache, "no_rast")) { fprintf(stderr, "disabling 3D acceleration\n"); FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1); } else if (tcl_mode == DRI_CONF_TCL_SW || !(rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL)) { if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) { rmesa->radeon.radeonScreen->chip_flags &= ~RADEON_CHIPSET_TCL; fprintf(stderr, "Disabling HW TCL support\n"); } TCL_FALLBACK(rmesa->radeon.glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1); } if (rmesa->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL) { /* _tnl_need_dlist_norm_lengths( ctx, GL_FALSE ); */ } _mesa_compute_version(ctx); if (ctx->VersionMajor < major_version || (ctx->VersionMajor == major_version && ctx->VersionMinor < minor_version)) { radeonDestroyContext(driContextPriv); *error = __DRI_CTX_ERROR_BAD_VERSION; return GL_FALSE; } *error = __DRI_CTX_ERROR_SUCCESS; return GL_TRUE; }
static void brw_initialize_context_constants(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; ctx->Const.QueryCounterBits.Timestamp = 36; ctx->Const.StripTextureBorder = true; ctx->Const.MaxDualSourceDrawBuffers = 1; ctx->Const.MaxDrawBuffers = BRW_MAX_DRAW_BUFFERS; ctx->Const.FragmentProgram.MaxTextureImageUnits = BRW_MAX_TEX_UNIT; ctx->Const.MaxTextureCoordUnits = 8; /* Mesa limit */ ctx->Const.MaxTextureUnits = MIN2(ctx->Const.MaxTextureCoordUnits, ctx->Const.FragmentProgram.MaxTextureImageUnits); ctx->Const.VertexProgram.MaxTextureImageUnits = BRW_MAX_TEX_UNIT; if (brw->gen >= 7) ctx->Const.GeometryProgram.MaxTextureImageUnits = BRW_MAX_TEX_UNIT; else ctx->Const.GeometryProgram.MaxTextureImageUnits = 0; ctx->Const.MaxCombinedTextureImageUnits = ctx->Const.VertexProgram.MaxTextureImageUnits + ctx->Const.FragmentProgram.MaxTextureImageUnits + ctx->Const.GeometryProgram.MaxTextureImageUnits; ctx->Const.MaxTextureLevels = 14; /* 8192 */ if (ctx->Const.MaxTextureLevels > MAX_TEXTURE_LEVELS) ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS; ctx->Const.Max3DTextureLevels = 9; ctx->Const.MaxCubeTextureLevels = 12; if (brw->gen >= 7) ctx->Const.MaxArrayTextureLayers = 2048; else ctx->Const.MaxArrayTextureLayers = 512; ctx->Const.MaxTextureRectSize = 1 << 12; ctx->Const.MaxTextureMaxAnisotropy = 16.0; ctx->Const.MaxRenderbufferSize = 8192; /* Hardware only supports a limited number of transform feedback buffers. * So we need to override the Mesa default (which is based only on software * limits). */ ctx->Const.MaxTransformFeedbackBuffers = BRW_MAX_SOL_BUFFERS; /* On Gen6, in the worst case, we use up one binding table entry per * transform feedback component (see comments above the definition of * BRW_MAX_SOL_BINDINGS, in brw_context.h), so we need to advertise a value * for MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS equal to * BRW_MAX_SOL_BINDINGS. * * In "separate components" mode, we need to divide this value by * BRW_MAX_SOL_BUFFERS, so that the total number of binding table entries * used up by all buffers will not exceed BRW_MAX_SOL_BINDINGS. */ ctx->Const.MaxTransformFeedbackInterleavedComponents = BRW_MAX_SOL_BINDINGS; ctx->Const.MaxTransformFeedbackSeparateComponents = BRW_MAX_SOL_BINDINGS / BRW_MAX_SOL_BUFFERS; ctx->Const.AlwaysUseGetTransformFeedbackVertexCount = true; const int max_samples = brw_supported_msaa_modes(brw)[0]; ctx->Const.MaxSamples = max_samples; ctx->Const.MaxColorTextureSamples = max_samples; ctx->Const.MaxDepthTextureSamples = max_samples; ctx->Const.MaxIntegerSamples = max_samples; if (brw->gen >= 7) ctx->Const.MaxProgramTextureGatherComponents = 4; ctx->Const.MinLineWidth = 1.0; ctx->Const.MinLineWidthAA = 1.0; ctx->Const.MaxLineWidth = 5.0; ctx->Const.MaxLineWidthAA = 5.0; ctx->Const.LineWidthGranularity = 0.5; ctx->Const.MinPointSize = 1.0; ctx->Const.MinPointSizeAA = 1.0; ctx->Const.MaxPointSize = 255.0; ctx->Const.MaxPointSizeAA = 255.0; ctx->Const.PointSizeGranularity = 1.0; if (brw->gen >= 5 || brw->is_g4x) ctx->Const.MaxClipPlanes = 8; ctx->Const.VertexProgram.MaxNativeInstructions = 16 * 1024; ctx->Const.VertexProgram.MaxAluInstructions = 0; ctx->Const.VertexProgram.MaxTexInstructions = 0; ctx->Const.VertexProgram.MaxTexIndirections = 0; ctx->Const.VertexProgram.MaxNativeAluInstructions = 0; ctx->Const.VertexProgram.MaxNativeTexInstructions = 0; ctx->Const.VertexProgram.MaxNativeTexIndirections = 0; ctx->Const.VertexProgram.MaxNativeAttribs = 16; ctx->Const.VertexProgram.MaxNativeTemps = 256; ctx->Const.VertexProgram.MaxNativeAddressRegs = 1; ctx->Const.VertexProgram.MaxNativeParameters = 1024; ctx->Const.VertexProgram.MaxEnvParams = MIN2(ctx->Const.VertexProgram.MaxNativeParameters, ctx->Const.VertexProgram.MaxEnvParams); ctx->Const.FragmentProgram.MaxNativeInstructions = 1024; ctx->Const.FragmentProgram.MaxNativeAluInstructions = 1024; ctx->Const.FragmentProgram.MaxNativeTexInstructions = 1024; ctx->Const.FragmentProgram.MaxNativeTexIndirections = 1024; ctx->Const.FragmentProgram.MaxNativeAttribs = 12; ctx->Const.FragmentProgram.MaxNativeTemps = 256; ctx->Const.FragmentProgram.MaxNativeAddressRegs = 0; ctx->Const.FragmentProgram.MaxNativeParameters = 1024; ctx->Const.FragmentProgram.MaxEnvParams = MIN2(ctx->Const.FragmentProgram.MaxNativeParameters, ctx->Const.FragmentProgram.MaxEnvParams); /* Fragment shaders use real, 32-bit twos-complement integers for all * integer types. */ ctx->Const.FragmentProgram.LowInt.RangeMin = 31; ctx->Const.FragmentProgram.LowInt.RangeMax = 30; ctx->Const.FragmentProgram.LowInt.Precision = 0; ctx->Const.FragmentProgram.HighInt = ctx->Const.FragmentProgram.LowInt; ctx->Const.FragmentProgram.MediumInt = ctx->Const.FragmentProgram.LowInt; if (brw->gen >= 7) { ctx->Const.FragmentProgram.MaxAtomicCounters = MAX_ATOMIC_COUNTERS; ctx->Const.VertexProgram.MaxAtomicCounters = MAX_ATOMIC_COUNTERS; ctx->Const.GeometryProgram.MaxAtomicCounters = MAX_ATOMIC_COUNTERS; ctx->Const.FragmentProgram.MaxAtomicBuffers = BRW_MAX_ABO; ctx->Const.VertexProgram.MaxAtomicBuffers = BRW_MAX_ABO; ctx->Const.GeometryProgram.MaxAtomicBuffers = BRW_MAX_ABO; ctx->Const.MaxCombinedAtomicBuffers = 3 * BRW_MAX_ABO; } /* Gen6 converts quads to polygon in beginning of 3D pipeline, * but we're not sure how it's actually done for vertex order, * that affect provoking vertex decision. Always use last vertex * convention for quad primitive which works as expected for now. */ if (brw->gen >= 6) ctx->Const.QuadsFollowProvokingVertexConvention = false; ctx->Const.NativeIntegers = true; ctx->Const.UniformBooleanTrue = 1; /* From the gen4 PRM, volume 4 page 127: * * "For SURFTYPE_BUFFER non-rendertarget surfaces, this field specifies * the base address of the first element of the surface, computed in * software by adding the surface base address to the byte offset of * the element in the buffer." * * However, unaligned accesses are slower, so enforce buffer alignment. */ ctx->Const.UniformBufferOffsetAlignment = 16; ctx->Const.TextureBufferOffsetAlignment = 16; if (brw->gen >= 6) { ctx->Const.MaxVarying = 32; ctx->Const.VertexProgram.MaxOutputComponents = 128; ctx->Const.GeometryProgram.MaxInputComponents = 64; ctx->Const.GeometryProgram.MaxOutputComponents = 128; ctx->Const.FragmentProgram.MaxInputComponents = 128; } /* We want the GLSL compiler to emit code that uses condition codes */ for (int i = 0; i < MESA_SHADER_TYPES; i++) { ctx->ShaderCompilerOptions[i].MaxIfDepth = brw->gen < 6 ? 16 : UINT_MAX; ctx->ShaderCompilerOptions[i].EmitCondCodes = true; ctx->ShaderCompilerOptions[i].EmitNoNoise = true; ctx->ShaderCompilerOptions[i].EmitNoMainReturn = true; ctx->ShaderCompilerOptions[i].EmitNoIndirectInput = true; ctx->ShaderCompilerOptions[i].EmitNoIndirectOutput = true; ctx->ShaderCompilerOptions[i].EmitNoIndirectUniform = (i == MESA_SHADER_FRAGMENT); ctx->ShaderCompilerOptions[i].EmitNoIndirectTemp = (i == MESA_SHADER_FRAGMENT); ctx->ShaderCompilerOptions[i].LowerClipDistance = true; } ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].PreferDP4 = true; }
/* * As above, but write stencil values. */ void _swrast_write_zoomed_stencil_span( GLcontext *ctx, GLuint n, GLint x, GLint y, const GLstencil stencil[], GLint y0, GLint skipPixels ) { GLint m; GLint r0, r1, row, r; GLint i, j, skipcol; GLstencil zstencil[MAX_WIDTH]; /* zoomed stencil values */ GLint maxwidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH ); (void) skipPixels; /* XXX this shouldn't be ignored */ /* compute width of output row */ m = (GLint) FABSF( n * ctx->Pixel.ZoomX ); if (m==0) { return; } if (ctx->Pixel.ZoomX<0.0) { /* adjust x coordinate for left/right mirroring */ x = x - m; } /* compute which rows to draw */ row = y - y0; r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY); r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY); if (r0==r1) { return; } else if (r1<r0) { GLint rtmp = r1; r1 = r0; r0 = rtmp; } /* return early if r0...r1 is above or below window */ if (r0<0 && r1<0) { /* below window */ return; } if (r0 >= (GLint) ctx->DrawBuffer->Height && r1 >= (GLint) ctx->DrawBuffer->Height) { /* above window */ return; } /* check if left edge is outside window */ skipcol = 0; if (x<0) { skipcol = -x; m += x; } /* make sure span isn't too long or short */ if (m>maxwidth) { m = maxwidth; } else if (m<=0) { return; } ASSERT( m <= MAX_WIDTH ); /* zoom the span horizontally */ if (ctx->Pixel.ZoomX==-1.0F) { /* n==m */ for (j=0;j<m;j++) { i = n - (j+skipcol) - 1; zstencil[j] = stencil[i]; } } else { GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; for (j=0;j<m;j++) { i = (GLint) ((j+skipcol) * xscale); if (i<0) i = n + i - 1; zstencil[j] = stencil[i]; } } /* write the span */ for (r=r0; r<r1; r++) { _swrast_write_stencil_span( ctx, m, x+skipcol, r, zstencil ); } }
/* called from within the core where_is_pose loop, all animsystems and constraints were executed & assigned. Now as last we do an IK pass */ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) { float R_parmat[3][3], identity[3][3]; float iR_parmat[3][3]; float R_bonemat[3][3]; float goalrot[3][3], goalpos[3]; float rootmat[4][4], imat[4][4]; float goal[4][4], goalinv[4][4]; float irest_basis[3][3], full_basis[3][3]; float end_pose[4][4], world_pose[4][4]; float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL; float resultinf=0.0f; int a, flag, hasstretch=0, resultblend=0; bPoseChannel *pchan; IK_Segment *seg, *parent, **iktree, *iktarget; IK_Solver *solver; PoseTarget *target; bKinematicConstraint *data, *poleangledata=NULL; Bone *bone; if (tree->totchannel == 0) return; iktree= MEM_mallocN(sizeof(void*)*tree->totchannel, "ik tree"); for(a=0; a<tree->totchannel; a++) { pchan= tree->pchan[a]; bone= pchan->bone; /* set DoF flag */ flag= 0; if(!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP)) flag |= IK_XDOF; if(!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP)) flag |= IK_YDOF; if(!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP)) flag |= IK_ZDOF; if(tree->stretch && (pchan->ikstretch > 0.0)) { flag |= IK_TRANS_YDOF; hasstretch = 1; } seg= iktree[a]= IK_CreateSegment(flag); /* find parent */ if(a == 0) parent= NULL; else parent= iktree[tree->parent[a]]; IK_SetParent(seg, parent); /* get the matrix that transforms from prevbone into this bone */ copy_m3_m4(R_bonemat, pchan->pose_mat); /* gather transformations for this IK segment */ if (pchan->parent) copy_m3_m4(R_parmat, pchan->parent->pose_mat); else unit_m3(R_parmat); /* bone offset */ if (pchan->parent && (a > 0)) sub_v3_v3v3(start, pchan->pose_head, pchan->parent->pose_tail); else /* only root bone (a = 0) has no parent */ start[0]= start[1]= start[2]= 0.0f; /* change length based on bone size */ length= bone->length*len_v3(R_bonemat[1]); /* compute rest basis and its inverse */ copy_m3_m3(rest_basis, bone->bone_mat); copy_m3_m3(irest_basis, bone->bone_mat); transpose_m3(irest_basis); /* compute basis with rest_basis removed */ invert_m3_m3(iR_parmat, R_parmat); mul_m3_m3m3(full_basis, iR_parmat, R_bonemat); mul_m3_m3m3(basis, irest_basis, full_basis); /* basis must be pure rotation */ normalize_m3(basis); /* transform offset into local bone space */ normalize_m3(iR_parmat); mul_m3_v3(iR_parmat, start); IK_SetTransform(seg, start, rest_basis, basis, length); if (pchan->ikflag & BONE_IK_XLIMIT) IK_SetLimit(seg, IK_X, pchan->limitmin[0], pchan->limitmax[0]); if (pchan->ikflag & BONE_IK_YLIMIT) IK_SetLimit(seg, IK_Y, pchan->limitmin[1], pchan->limitmax[1]); if (pchan->ikflag & BONE_IK_ZLIMIT) IK_SetLimit(seg, IK_Z, pchan->limitmin[2], pchan->limitmax[2]); IK_SetStiffness(seg, IK_X, pchan->stiffness[0]); IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]); IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]); if(tree->stretch && (pchan->ikstretch > 0.0)) { float ikstretch = pchan->ikstretch*pchan->ikstretch; IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0-ikstretch, 0.99)); IK_SetLimit(seg, IK_TRANS_Y, 0.001, 1e10); } } solver= IK_CreateSolver(iktree[0]); /* set solver goals */ /* first set the goal inverse transform, assuming the root of tree was done ok! */ pchan= tree->pchan[0]; if (pchan->parent) /* transform goal by parent mat, so this rotation is not part of the segment's basis. otherwise rotation limits do not work on the local transform of the segment itself. */ copy_m4_m4(rootmat, pchan->parent->pose_mat); else unit_m4(rootmat); VECCOPY(rootmat[3], pchan->pose_head); mul_m4_m4m4(imat, rootmat, ob->obmat); invert_m4_m4(goalinv, imat); for (target=tree->targets.first; target; target=target->next) { float polepos[3]; int poleconstrain= 0; data= (bKinematicConstraint*)target->con->data; /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though * strictly speaking, it is a posechannel) */ get_constraint_target_matrix(scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); /* and set and transform goal */ mul_m4_m4m4(goal, rootmat, goalinv); VECCOPY(goalpos, goal[3]); copy_m3_m4(goalrot, goal); /* same for pole vector target */ if(data->poletar) { get_constraint_target_matrix(scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); if(data->flag & CONSTRAINT_IK_SETANGLE) { /* don't solve IK when we are setting the pole angle */ break; } else { mul_m4_m4m4(goal, rootmat, goalinv); VECCOPY(polepos, goal[3]); poleconstrain= 1; /* for pole targets, we blend the result of the ik solver * instead of the target position, otherwise we can't get * a smooth transition */ resultblend= 1; resultinf= target->con->enforce; if(data->flag & CONSTRAINT_IK_GETANGLE) { poleangledata= data; data->flag &= ~CONSTRAINT_IK_GETANGLE; } } } /* do we need blending? */ if (!resultblend && target->con->enforce!=1.0) { float q1[4], q2[4], q[4]; float fac= target->con->enforce; float mfac= 1.0-fac; pchan= tree->pchan[target->tip]; /* end effector in world space */ copy_m4_m4(end_pose, pchan->pose_mat); VECCOPY(end_pose[3], pchan->pose_tail); mul_serie_m4(world_pose, goalinv, ob->obmat, end_pose, NULL, NULL, NULL, NULL, NULL); /* blend position */ goalpos[0]= fac*goalpos[0] + mfac*world_pose[3][0]; goalpos[1]= fac*goalpos[1] + mfac*world_pose[3][1]; goalpos[2]= fac*goalpos[2] + mfac*world_pose[3][2]; /* blend rotation */ mat3_to_quat( q1,goalrot); mat4_to_quat( q2,world_pose); interp_qt_qtqt(q, q1, q2, mfac); quat_to_mat3( goalrot,q); } iktarget= iktree[target->tip]; if(data->weight != 0.0) { if(poleconstrain) IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, polepos, data->poleangle, (poleangledata == data)); IK_SolverAddGoal(solver, iktarget, goalpos, data->weight); } if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0)) if((data->flag & CONSTRAINT_IK_AUTO)==0) IK_SolverAddGoalOrientation(solver, iktarget, goalrot, data->orientweight); } /* solve */ IK_Solve(solver, 0.0f, tree->iterations); if(poleangledata) poleangledata->poleangle= IK_SolverGetPoleAngle(solver); IK_FreeSolver(solver); /* gather basis changes */ tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change"); if(hasstretch) ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch"); for(a=0; a<tree->totchannel; a++) { IK_GetBasisChange(iktree[a], tree->basis_change[a]); if(hasstretch) { /* have to compensate for scaling received from parent */ float parentstretch, stretch; pchan= tree->pchan[a]; parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0; if(tree->stretch && (pchan->ikstretch > 0.0)) { float trans[3], length; IK_GetTranslationChange(iktree[a], trans); length= pchan->bone->length*len_v3(pchan->pose_mat[1]); ikstretch[a]= (length == 0.0)? 1.0: (trans[1]+length)/length; } else ikstretch[a] = 1.0; stretch= (parentstretch == 0.0)? 1.0: ikstretch[a]/parentstretch; mul_v3_fl(tree->basis_change[a][0], stretch); mul_v3_fl(tree->basis_change[a][1], stretch); mul_v3_fl(tree->basis_change[a][2], stretch); } if(resultblend && resultinf!=1.0f) { unit_m3(identity); blend_m3_m3m3(tree->basis_change[a], identity, tree->basis_change[a], resultinf); } IK_FreeSegment(iktree[a]); } MEM_freeN(iktree); if(ikstretch) MEM_freeN(ikstretch); }
void Klass::initialize_supers(Klass* k, TRAPS) { if (FastSuperclassLimit == 0) { // None of the other machinery matters. set_super(k); return; } if (k == NULL) { set_super(NULL); _primary_supers[0] = this; assert(super_depth() == 0, "Object must already be initialized properly"); } else if (k != super() || k == SystemDictionary::Object_klass()) { assert(super() == NULL || super() == SystemDictionary::Object_klass(), "initialize this only once to a non-trivial value"); set_super(k); Klass* sup = k; int sup_depth = sup->super_depth(); juint my_depth = MIN2(sup_depth + 1, (int)primary_super_limit()); if (!can_be_primary_super_slow()) my_depth = primary_super_limit(); for (juint i = 0; i < my_depth; i++) { _primary_supers[i] = sup->_primary_supers[i]; } Klass* *super_check_cell; if (my_depth < primary_super_limit()) { _primary_supers[my_depth] = this; super_check_cell = &_primary_supers[my_depth]; } else { // Overflow of the primary_supers array forces me to be secondary. super_check_cell = &_secondary_super_cache; } set_super_check_offset((address)super_check_cell - (address) this); #ifdef ASSERT { juint j = super_depth(); assert(j == my_depth, "computed accessor gets right answer"); Klass* t = this; while (!t->can_be_primary_super()) { t = t->super(); j = t->super_depth(); } for (juint j1 = j+1; j1 < primary_super_limit(); j1++) { assert(primary_super_of_depth(j1) == NULL, "super list padding"); } while (t != NULL) { assert(primary_super_of_depth(j) == t, "super list initialization"); t = t->super(); --j; } assert(j == (juint)-1, "correct depth count"); } #endif } if (secondary_supers() == NULL) { KlassHandle this_kh (THREAD, this); // Now compute the list of secondary supertypes. // Secondaries can occasionally be on the super chain, // if the inline "_primary_supers" array overflows. int extras = 0; Klass* p; for (p = super(); !(p == NULL || p->can_be_primary_super()); p = p->super()) { ++extras; } ResourceMark rm(THREAD); // need to reclaim GrowableArrays allocated below // Compute the "real" non-extra secondaries. GrowableArray<Klass*>* secondaries = compute_secondary_supers(extras); if (secondaries == NULL) { // secondary_supers set by compute_secondary_supers return; } GrowableArray<Klass*>* primaries = new GrowableArray<Klass*>(extras); for (p = this_kh->super(); !(p == NULL || p->can_be_primary_super()); p = p->super()) { int i; // Scan for overflow primaries being duplicates of 2nd'arys // This happens frequently for very deeply nested arrays: the // primary superclass chain overflows into the secondary. The // secondary list contains the element_klass's secondaries with // an extra array dimension added. If the element_klass's // secondary list already contains some primary overflows, they // (with the extra level of array-ness) will collide with the // normal primary superclass overflows. for( i = 0; i < secondaries->length(); i++ ) { if( secondaries->at(i) == p ) break; } if( i < secondaries->length() ) continue; // It's a dup, don't put it in primaries->push(p); } // Combine the two arrays into a metadata object to pack the array. // The primaries are added in the reverse order, then the secondaries. int new_length = primaries->length() + secondaries->length(); Array<Klass*>* s2 = MetadataFactory::new_array<Klass*>( class_loader_data(), new_length, CHECK); int fill_p = primaries->length(); for (int j = 0; j < fill_p; j++) { s2->at_put(j, primaries->pop()); // add primaries in reverse order. } for( int j = 0; j < secondaries->length(); j++ ) { s2->at_put(j+fill_p, secondaries->at(j)); // add secondaries on the end. } #ifdef ASSERT // We must not copy any NULL placeholders left over from bootstrap. for (int j = 0; j < s2->length(); j++) { assert(s2->at(j) != NULL, "correct bootstrapping order"); } #endif this_kh->set_secondary_supers(s2); } }
/** * Compute which mipmap levels that really need to be sent to the hardware. * This depends on the base image size, GL_TEXTURE_MIN_LOD, * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. */ static void intel_calculate_first_last_level(struct intel_texture_object *intelObj) { struct gl_texture_object *tObj = &intelObj->base; const struct gl_texture_image *const baseImage = tObj->Image[0][tObj->BaseLevel]; /* These must be signed values. MinLod and MaxLod can be negative numbers, * and having firstLevel and lastLevel as signed prevents the need for * extra sign checks. */ int firstLevel; int lastLevel; /* Yes, this looks overly complicated, but it's all needed. */ switch (tObj->Target) { case GL_TEXTURE_1D: case GL_TEXTURE_2D: case GL_TEXTURE_3D: case GL_TEXTURE_CUBE_MAP: if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. */ firstLevel = lastLevel = tObj->BaseLevel; } else { #ifdef I915 firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5); firstLevel = MAX2(firstLevel, tObj->BaseLevel); firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2); lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5); lastLevel = MAX2(lastLevel, tObj->BaseLevel); lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); lastLevel = MIN2(lastLevel, tObj->MaxLevel); lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ #else /* Currently not taking min/max lod into account here, those * values are programmed as sampler state elsewhere and we * upload the same mipmap levels regardless. Not sure if * this makes sense as it means it isn't possible for the app * to use min/max lod to reduce texture memory pressure: */ firstLevel = tObj->BaseLevel; lastLevel = MIN2(tObj->BaseLevel + baseImage->MaxLog2, tObj->MaxLevel); lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ #endif } break; case GL_TEXTURE_RECTANGLE_NV: case GL_TEXTURE_4D_SGIS: firstLevel = lastLevel = 0; break; default: return; } /* save these values */ intelObj->firstLevel = firstLevel; intelObj->lastLevel = lastLevel; }
/* only creates a table for a single channel in CurveMapping */ static void curvemap_make_table(CurveMap *cuma, rctf *clipr) { CurveMapPoint *cmp= cuma->curve; BezTriple *bezt; float *fp, *allpoints, *lastpoint, curf, range; int a, totpoint; if(cuma->curve==NULL) return; /* default rect also is table range */ cuma->mintable= clipr->xmin; cuma->maxtable= clipr->xmax; /* hrmf... we now rely on blender ipo beziers, these are more advanced */ bezt= MEM_callocN(cuma->totpoint*sizeof(BezTriple), "beztarr"); for(a=0; a<cuma->totpoint; a++) { cuma->mintable= MIN2(cuma->mintable, cmp[a].x); cuma->maxtable= MAX2(cuma->maxtable, cmp[a].x); bezt[a].vec[1][0]= cmp[a].x; bezt[a].vec[1][1]= cmp[a].y; if(cmp[a].flag & CUMA_VECTOR) bezt[a].h1= bezt[a].h2= HD_VECT; else bezt[a].h1= bezt[a].h2= HD_AUTO; } for(a=0; a<cuma->totpoint; a++) { if(a==0) calchandle_curvemap(bezt, NULL, bezt+1, 0); else if(a==cuma->totpoint-1) calchandle_curvemap(bezt+a, bezt+a-1, NULL, 0); else calchandle_curvemap(bezt+a, bezt+a-1, bezt+a+1, 0); } /* first and last handle need correction, instead of pointing to center of next/prev, we let it point to the closest handle */ if(cuma->totpoint>2) { float hlen, nlen, vec[3]; if(bezt[0].h2==HD_AUTO) { hlen= len_v3v3(bezt[0].vec[1], bezt[0].vec[2]); /* original handle length */ /* clip handle point */ VECCOPY(vec, bezt[1].vec[0]); if(vec[0] < bezt[0].vec[1][0]) vec[0]= bezt[0].vec[1][0]; sub_v3_v3(vec, bezt[0].vec[1]); nlen= len_v3(vec); if(nlen>FLT_EPSILON) { mul_v3_fl(vec, hlen/nlen); add_v3_v3v3(bezt[0].vec[2], vec, bezt[0].vec[1]); sub_v3_v3v3(bezt[0].vec[0], bezt[0].vec[1], vec); } } a= cuma->totpoint-1; if(bezt[a].h2==HD_AUTO) { hlen= len_v3v3(bezt[a].vec[1], bezt[a].vec[0]); /* original handle length */ /* clip handle point */ VECCOPY(vec, bezt[a-1].vec[2]); if(vec[0] > bezt[a].vec[1][0]) vec[0]= bezt[a].vec[1][0]; sub_v3_v3(vec, bezt[a].vec[1]); nlen= len_v3(vec); if(nlen>FLT_EPSILON) { mul_v3_fl(vec, hlen/nlen); add_v3_v3v3(bezt[a].vec[0], vec, bezt[a].vec[1]); sub_v3_v3v3(bezt[a].vec[2], bezt[a].vec[1], vec); } } } /* make the bezier curve */ if(cuma->table) MEM_freeN(cuma->table); totpoint= (cuma->totpoint-1)*CM_RESOL; fp= allpoints= MEM_callocN(totpoint*2*sizeof(float), "table"); for(a=0; a<cuma->totpoint-1; a++, fp += 2*CM_RESOL) { correct_bezpart(bezt[a].vec[1], bezt[a].vec[2], bezt[a+1].vec[0], bezt[a+1].vec[1]); forward_diff_bezier(bezt[a].vec[1][0], bezt[a].vec[2][0], bezt[a+1].vec[0][0], bezt[a+1].vec[1][0], fp, CM_RESOL-1, 2*sizeof(float)); forward_diff_bezier(bezt[a].vec[1][1], bezt[a].vec[2][1], bezt[a+1].vec[0][1], bezt[a+1].vec[1][1], fp+1, CM_RESOL-1, 2*sizeof(float)); } /* store first and last handle for extrapolation, unit length */ cuma->ext_in[0]= bezt[0].vec[0][0] - bezt[0].vec[1][0]; cuma->ext_in[1]= bezt[0].vec[0][1] - bezt[0].vec[1][1]; range= sqrt(cuma->ext_in[0]*cuma->ext_in[0] + cuma->ext_in[1]*cuma->ext_in[1]); cuma->ext_in[0]/= range; cuma->ext_in[1]/= range; a= cuma->totpoint-1; cuma->ext_out[0]= bezt[a].vec[1][0] - bezt[a].vec[2][0]; cuma->ext_out[1]= bezt[a].vec[1][1] - bezt[a].vec[2][1]; range= sqrt(cuma->ext_out[0]*cuma->ext_out[0] + cuma->ext_out[1]*cuma->ext_out[1]); cuma->ext_out[0]/= range; cuma->ext_out[1]/= range; /* cleanup */ MEM_freeN(bezt); range= CM_TABLEDIV*(cuma->maxtable - cuma->mintable); cuma->range= 1.0f/range; /* now make a table with CM_TABLE equal x distances */ fp= allpoints; lastpoint= allpoints + 2*(totpoint-1); cmp= MEM_callocN((CM_TABLE+1)*sizeof(CurveMapPoint), "dist table"); for(a=0; a<=CM_TABLE; a++) { curf= cuma->mintable + range*(float)a; cmp[a].x= curf; /* get the first x coordinate larger than curf */ while(curf >= fp[0] && fp!=lastpoint) { fp+=2; } if(fp==allpoints || (curf >= fp[0] && fp==lastpoint)) cmp[a].y= curvemap_calc_extend(cuma, curf, allpoints, lastpoint); else { float fac1= fp[0] - fp[-2]; float fac2= fp[0] - curf; if(fac1 > FLT_EPSILON) fac1= fac2/fac1; else fac1= 0.0f; cmp[a].y= fac1*fp[-1] + (1.0f-fac1)*fp[1]; } } MEM_freeN(allpoints); cuma->table= cmp; }
/** * Draw vertex arrays. * This is the main entrypoint into the drawing module. If drawing an indexed * primitive, the draw_set_indexes() function should have already been called * to specify the element/index buffer information. */ void draw_vbo(struct draw_context *draw, const struct pipe_draw_info *info) { unsigned instance; unsigned index_limit; unsigned count; assert(info->instance_count > 0); if (info->indexed) assert(draw->pt.user.elts); draw->pt.user.eltBias = info->index_bias; draw->pt.user.min_index = info->min_index; draw->pt.user.max_index = info->max_index; draw->pt.user.eltSize = info->indexed ? draw->pt.user.eltSizeIB : 0; if (0) debug_printf("draw_vbo(mode=%u start=%u count=%u):\n", info->mode, info->start, info->count); if (0) tgsi_dump(draw->vs.vertex_shader->state.tokens, 0); if (0) { unsigned int i; debug_printf("Elements:\n"); for (i = 0; i < draw->pt.nr_vertex_elements; i++) { debug_printf(" %u: src_offset=%u inst_div=%u vbuf=%u format=%s\n", i, draw->pt.vertex_element[i].src_offset, draw->pt.vertex_element[i].instance_divisor, draw->pt.vertex_element[i].vertex_buffer_index, util_format_name(draw->pt.vertex_element[i].src_format)); } debug_printf("Buffers:\n"); for (i = 0; i < draw->pt.nr_vertex_buffers; i++) { debug_printf(" %u: stride=%u offset=%u ptr=%p\n", i, draw->pt.vertex_buffer[i].stride, draw->pt.vertex_buffer[i].buffer_offset, draw->pt.user.vbuffer[i]); } } if (0) draw_print_arrays(draw, info->mode, info->start, MIN2(info->count, 20)); index_limit = util_draw_max_index(draw->pt.vertex_buffer, draw->pt.vertex_element, draw->pt.nr_vertex_elements, info); if (index_limit == 0) { /* one of the buffers is too small to do any valid drawing */ debug_warning("draw: VBO too small to draw anything\n"); return; } draw->pt.max_index = index_limit - 1; count = info->count; if (count == 0) { if (info->count_from_stream_output) count = draw->pt.max_index + 1; } /* * TODO: We could use draw->pt.max_index to further narrow * the min_index/max_index hints given by the state tracker. */ for (instance = 0; instance < info->instance_count; instance++) { draw->instance_id = instance + info->start_instance; if (info->primitive_restart) { draw_pt_arrays_restart(draw, info); } else { draw_pt_arrays(draw, info->mode, info->start, count); } } }
int vc4_simulator_flush(struct vc4_context *vc4, struct drm_vc4_submit_cl *args) { struct vc4_screen *screen = vc4->screen; struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]); struct vc4_resource *ctex = csurf ? vc4_resource(csurf->base.texture) : NULL; uint32_t winsys_stride = ctex ? ctex->bo->simulator_winsys_stride : 0; uint32_t sim_stride = ctex ? ctex->slices[0].stride : 0; uint32_t row_len = MIN2(sim_stride, winsys_stride); struct vc4_exec_info exec; struct drm_device local_dev = { .vc4 = vc4, .simulator_mem_next = OVERFLOW_SIZE, }; struct drm_device *dev = &local_dev; int ret; memset(&exec, 0, sizeof(exec)); list_inithead(&exec.unref_list); if (ctex && ctex->bo->simulator_winsys_map) { #if 0 fprintf(stderr, "%dx%d %d %d %d\n", ctex->base.b.width0, ctex->base.b.height0, winsys_stride, sim_stride, ctex->bo->size); #endif for (int y = 0; y < ctex->base.b.height0; y++) { memcpy(ctex->bo->map + y * sim_stride, ctex->bo->simulator_winsys_map + y * winsys_stride, row_len); } } exec.args = args; ret = vc4_simulator_pin_bos(dev, &exec); if (ret) return ret; ret = vc4_cl_validate(dev, &exec); if (ret) return ret; if (vc4_debug & VC4_DEBUG_CL) { fprintf(stderr, "RCL:\n"); vc4_dump_cl(screen->simulator_mem_base + exec.ct1ca, exec.ct1ea - exec.ct1ca, true); } if (exec.ct0ca != exec.ct0ea) { int bfc = simpenrose_do_binning(exec.ct0ca, exec.ct0ea); if (bfc != 1) { fprintf(stderr, "Binning returned %d flushes, should be 1.\n", bfc); fprintf(stderr, "Relocated binning command list:\n"); vc4_dump_cl(screen->simulator_mem_base + exec.ct0ca, exec.ct0ea - exec.ct0ca, false); abort(); } } int rfc = simpenrose_do_rendering(exec.ct1ca, exec.ct1ea); if (rfc != 1) { fprintf(stderr, "Rendering returned %d frames, should be 1.\n", rfc); fprintf(stderr, "Relocated render command list:\n"); vc4_dump_cl(screen->simulator_mem_base + exec.ct1ca, exec.ct1ea - exec.ct1ca, true); abort(); } ret = vc4_simulator_unpin_bos(&exec); if (ret) return ret; list_for_each_entry_safe(struct drm_vc4_bo, bo, &exec.unref_list, unref_head) { list_del(&bo->unref_head); assert(*(uint32_t *)(bo->base.vaddr + bo->bo->size) == BO_SENTINEL); vc4_bo_unreference(&bo->bo); free(bo); } if (ctex && ctex->bo->simulator_winsys_map) { for (int y = 0; y < ctex->base.b.height0; y++) { memcpy(ctex->bo->simulator_winsys_map + y * winsys_stride, ctex->bo->map + y * sim_stride, row_len); } } return 0; }
static void view3d_select_loop(ViewContext *vc, Scene *scene, View3D *v3d, ARegion *ar, bool use_obedit_skip) { short code = 1; char dt; short dtx; if (vc->obedit && vc->obedit->type == OB_MBALL) { draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR); } else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) { /* if not drawing sketch, draw bones */ if (!BDR_drawSketchNames(vc)) { draw_object(scene, ar, v3d, BASACT, DRAW_PICKING | DRAW_CONSTCOLOR); } } else { Base *base; v3d->xray = true; /* otherwise it postpones drawing */ for (base = scene->base.first; base; base = base->next) { if (base->lay & v3d->lay) { if ((base->object->restrictflag & OB_RESTRICT_SELECT) || (use_obedit_skip && (scene->obedit->data == base->object->data))) { base->selcol = 0; } else { base->selcol = code; if (GPU_select_load_id(code)) { draw_object(scene, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR); /* we draw duplicators for selection too */ if ((base->object->transflag & OB_DUPLI)) { ListBase *lb; DupliObject *dob; Base tbase; tbase.flag = OB_FROMDUPLI; lb = object_duplilist(G.main->eval_ctx, scene, base->object); for (dob = lb->first; dob; dob = dob->next) { float omat[4][4]; tbase.object = dob->ob; copy_m4_m4(omat, dob->ob->obmat); copy_m4_m4(dob->ob->obmat, dob->mat); /* extra service: draw the duplicator in drawtype of parent */ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt); dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx; draw_object(scene, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR); tbase.object->dt = dt; tbase.object->dtx = dtx; copy_m4_m4(dob->ob->obmat, omat); } free_object_duplilist(lb); } } code++; } } } v3d->xray = false; /* restore */ } }
static void brw_update_sampler_state( const struct pipe_sampler_state *pipe_sampler, unsigned sdc_gs_offset, struct brw_sampler_state *sampler) { memset(sampler, 0, sizeof(*sampler)); switch (pipe_sampler->min_mip_filter) { case PIPE_TEX_FILTER_NEAREST: sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST; break; case PIPE_TEX_FILTER_LINEAR: sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR; break; case PIPE_TEX_FILTER_ANISO: sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC; break; default: break; } switch (pipe_sampler->min_mip_filter) { case PIPE_TEX_MIPFILTER_NEAREST: sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST; break; case PIPE_TEX_MIPFILTER_LINEAR: sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR; break; case PIPE_TEX_MIPFILTER_NONE: sampler->ss0.mip_filter = BRW_MIPFILTER_NONE; break; default: break; } /* Set Anisotropy: */ switch (pipe_sampler->mag_img_filter) { case PIPE_TEX_FILTER_NEAREST: sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST; break; case PIPE_TEX_FILTER_LINEAR: sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; break; case PIPE_TEX_FILTER_ANISO: sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR; break; default: break; } if (pipe_sampler->max_anisotropy > 2.0) { sampler->ss3.max_aniso = MAX2((pipe_sampler->max_anisotropy - 2) / 2, BRW_ANISORATIO_16); } sampler->ss1.s_wrap_mode = translate_wrap_mode(pipe_sampler->wrap_s); sampler->ss1.r_wrap_mode = translate_wrap_mode(pipe_sampler->wrap_r); sampler->ss1.t_wrap_mode = translate_wrap_mode(pipe_sampler->wrap_t); /* Fulsim complains if I don't do this. Hardware doesn't mind: */ #if 0 if (texObj->Target == GL_TEXTURE_CUBE_MAP_ARB) { sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE; sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE; sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE; } #endif /* Set shadow function: */ if (pipe_sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { /* Shadowing is "enabled" by emitting a particular sampler * message (sample_c). So need to recompile WM program when * shadow comparison is enabled on each/any texture unit. */ sampler->ss0.shadow_function = intel_translate_shadow_compare_func(pipe_sampler->compare_func); } /* Set LOD bias: */ sampler->ss0.lod_bias = S_FIXED(CLAMP(pipe_sampler->lod_bias, -16, 15), 6); sampler->ss0.lod_preclamp = 1; /* OpenGL mode */ sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */ /* Set BaseMipLevel, MaxLOD, MinLOD: * * XXX: I don't think that using firstLevel, lastLevel works, * because we always setup the surface state as if firstLevel == * level zero. Probably have to subtract firstLevel from each of * these: */ sampler->ss0.base_level = U_FIXED(0, 1); sampler->ss1.max_lod = U_FIXED(MIN2(MAX2(pipe_sampler->max_lod, 0), 13), 6); sampler->ss1.min_lod = U_FIXED(MIN2(MAX2(pipe_sampler->min_lod, 0), 13), 6); sampler->ss2.default_color_pointer = sdc_gs_offset >> 5; }
void piglit_init(int argc, char **argv) { GLuint vs_spiral, gs_spiral, vs_ref_main, vs_test_main, gs_test_main, gs_layout, fs_main, vao, element_buf; GLint max_gs_out_vertices, max_gs_out_components; int max_testable_vertices; char *text, *endptr; /* parse args */ if (argc != 2) print_usage_and_exit(argv[0]); endptr = NULL; num_vertices = strtol(argv[1], &endptr, 0); if (endptr != argv[1] + strlen(argv[1])) print_usage_and_exit(argv[0]); /* Figure out the maximum number of vertices we can test. */ glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &max_gs_out_vertices); glGetIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &max_gs_out_components); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); max_testable_vertices = MIN2(max_gs_out_vertices, max_gs_out_components / 4); /* If num_vertices == 0, test the maximum possible number of * vertices. Otherwise ensure that the requested number is * supported by the implementation. */ if (num_vertices == 0) num_vertices = max_testable_vertices; else if (num_vertices > max_testable_vertices) { printf("Can't test more than %d vertices\n", max_testable_vertices); piglit_report_result(PIGLIT_SKIP); } /* Compile shaders */ vs_spiral = piglit_compile_shader_text(GL_VERTEX_SHADER, spiral_text); gs_spiral = piglit_compile_shader_text(GL_GEOMETRY_SHADER, spiral_text); vs_ref_main = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_ref_text); vs_test_main = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_test_text); gs_test_main = piglit_compile_shader_text(GL_GEOMETRY_SHADER, gs_test_text); asprintf(&text, gs_layout_template, num_vertices); gs_layout = piglit_compile_shader_text(GL_GEOMETRY_SHADER, text); free(text); fs_main = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fs_text); prog_ref = glCreateProgram(); glAttachShader(prog_ref, vs_ref_main); glAttachShader(prog_ref, vs_spiral); glAttachShader(prog_ref, fs_main); glLinkProgram(prog_ref); if (!piglit_link_check_status(prog_ref)) piglit_report_result(PIGLIT_FAIL); prog_test = glCreateProgram(); glAttachShader(prog_test, vs_test_main); glAttachShader(prog_test, gs_test_main); glAttachShader(prog_test, gs_spiral); glAttachShader(prog_test, gs_layout); glAttachShader(prog_test, fs_main); glLinkProgram(prog_test); if (!piglit_link_check_status(prog_test)) piglit_report_result(PIGLIT_FAIL); glDeleteShader(vs_spiral); glDeleteShader(gs_spiral); glDeleteShader(vs_ref_main); glDeleteShader(vs_test_main); glDeleteShader(gs_test_main); glDeleteShader(gs_layout); glDeleteShader(fs_main); /* Various other GL objects needed by the test */ glGenVertexArrays(1, &vao); glBindVertexArray(vao); glGenBuffers(1, &element_buf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buf); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); }
/* Helper function for si_blit_decompress_zs_in_place. */ static void si_blit_decompress_zs_planes_in_place(struct si_context *sctx, struct r600_texture *texture, unsigned planes, unsigned level_mask, unsigned first_layer, unsigned last_layer) { struct pipe_surface *zsurf, surf_tmpl = {{0}}; unsigned layer, max_layer, checked_last_layer; unsigned fully_decompressed_mask = 0; if (!level_mask) return; if (planes & PIPE_MASK_S) sctx->db_flush_stencil_inplace = true; if (planes & PIPE_MASK_Z) sctx->db_flush_depth_inplace = true; si_mark_atom_dirty(sctx, &sctx->db_render_state); surf_tmpl.format = texture->resource.b.b.format; while (level_mask) { unsigned level = u_bit_scan(&level_mask); surf_tmpl.u.tex.level = level; /* The smaller the mipmap level, the less layers there are * as far as 3D textures are concerned. */ max_layer = util_max_layer(&texture->resource.b.b, level); checked_last_layer = MIN2(last_layer, max_layer); for (layer = first_layer; layer <= checked_last_layer; layer++) { surf_tmpl.u.tex.first_layer = layer; surf_tmpl.u.tex.last_layer = layer; zsurf = sctx->b.b.create_surface(&sctx->b.b, &texture->resource.b.b, &surf_tmpl); si_blitter_begin(&sctx->b.b, SI_DECOMPRESS); util_blitter_custom_depth_stencil(sctx->blitter, zsurf, NULL, ~0, sctx->custom_dsa_flush, 1.0f); si_blitter_end(&sctx->b.b); pipe_surface_reference(&zsurf, NULL); } /* The texture will always be dirty if some layers aren't flushed. * I don't think this case occurs often though. */ if (first_layer == 0 && last_layer == max_layer) { fully_decompressed_mask |= 1u << level; } } if (planes & PIPE_MASK_Z) texture->dirty_level_mask &= ~fully_decompressed_mask; if (planes & PIPE_MASK_S) texture->stencil_dirty_level_mask &= ~fully_decompressed_mask; sctx->db_flush_depth_inplace = false; sctx->db_flush_stencil_inplace = false; si_mark_atom_dirty(sctx, &sctx->db_render_state); }
static boolean try_setup_point( struct lp_setup_context *setup, const float (*v0)[4] ) { struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; /* x/y positions in fixed point */ const struct lp_setup_variant_key *key = &setup->setup.variant->key; const int sizeAttr = setup->psize_slot; const float size = (setup->point_size_per_vertex && sizeAttr > 0) ? v0[sizeAttr][0] : setup->point_size; /* Yes this is necessary to accurately calculate bounding boxes * with the two fill-conventions we support. GL (normally) ends * up needing a bottom-left fill convention, which requires * slightly different rounding. */ int adj = (setup->bottom_edge_rule != 0) ? 1 : 0; struct lp_scene *scene = setup->scene; struct lp_rast_triangle *point; unsigned bytes; struct u_rect bbox; unsigned nr_planes = 4; struct point_info info; unsigned viewport_index = 0; unsigned layer = 0; int fixed_width; if (setup->viewport_index_slot > 0) { unsigned *udata = (unsigned*)v0[setup->viewport_index_slot]; viewport_index = lp_clamp_viewport_idx(*udata); } if (setup->layer_slot > 0) { layer = *(unsigned*)v0[setup->layer_slot]; layer = MIN2(layer, scene->fb_max_layer); } if (0) print_point(setup, v0, size); /* Bounding rectangle (in pixels) */ if (!lp_context->rasterizer || lp_context->rasterizer->point_quad_rasterization) { /* * Rasterize points as quads. */ int x0, y0; /* Point size as fixed point integer, remove rounding errors * and gives minimum width for very small points. */ fixed_width = MAX2(FIXED_ONE, subpixel_snap(size)); x0 = subpixel_snap(v0[0][0] - setup->pixel_offset) - fixed_width/2; y0 = subpixel_snap(v0[0][1] - setup->pixel_offset) - fixed_width/2; bbox.x0 = (x0 + (FIXED_ONE-1)) >> FIXED_ORDER; bbox.x1 = (x0 + fixed_width + (FIXED_ONE-1)) >> FIXED_ORDER; bbox.y0 = (y0 + (FIXED_ONE-1) + adj) >> FIXED_ORDER; bbox.y1 = (y0 + fixed_width + (FIXED_ONE-1) + adj) >> FIXED_ORDER; /* Inclusive coordinates: */ bbox.x1--; bbox.y1--; } else {
/** * Create a new pipe_screen object * Note: we're not presently subclassing pipe_screen (no llvmpipe_screen). */ struct pipe_screen * llvmpipe_create_screen(struct sw_winsys *winsys) { struct llvmpipe_screen *screen; util_cpu_detect(); #if defined(PIPE_ARCH_X86) && HAVE_LLVM < 0x0302 /* require SSE2 due to LLVM PR6960. */ if (!util_cpu_caps.has_sse2) return NULL; #endif #ifdef DEBUG LP_DEBUG = debug_get_flags_option("LP_DEBUG", lp_debug_flags, 0 ); #endif LP_PERF = debug_get_flags_option("LP_PERF", lp_perf_flags, 0 ); screen = CALLOC_STRUCT(llvmpipe_screen); if (!screen) return NULL; screen->winsys = winsys; screen->base.destroy = llvmpipe_destroy_screen; screen->base.get_name = llvmpipe_get_name; screen->base.get_vendor = llvmpipe_get_vendor; screen->base.get_param = llvmpipe_get_param; screen->base.get_shader_param = llvmpipe_get_shader_param; screen->base.get_paramf = llvmpipe_get_paramf; screen->base.is_format_supported = llvmpipe_is_format_supported; screen->base.context_create = llvmpipe_create_context; screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer; screen->base.fence_reference = llvmpipe_fence_reference; screen->base.fence_signalled = llvmpipe_fence_signalled; screen->base.fence_finish = llvmpipe_fence_finish; screen->base.get_timestamp = llvmpipe_get_timestamp; llvmpipe_init_screen_resource_funcs(&screen->base); lp_jit_screen_init(screen); screen->num_threads = util_cpu_caps.nr_cpus > 1 ? util_cpu_caps.nr_cpus : 0; #ifdef PIPE_SUBSYSTEM_EMBEDDED screen->num_threads = 0; #endif screen->num_threads = debug_get_num_option("LP_NUM_THREADS", screen->num_threads); screen->num_threads = MIN2(screen->num_threads, LP_MAX_THREADS); screen->rast = lp_rast_create(screen->num_threads); if (!screen->rast) { lp_jit_screen_cleanup(screen); FREE(screen); return NULL; } pipe_mutex_init(screen->rast_mutex); util_format_s3tc_init(); return &screen->base; }
/** * Set up for drawing interleaved arrays that all live in one VBO * or all live in user space. * \param vbuffer returns vertex buffer info * \param velements returns vertex element info */ static boolean setup_interleaved_attribs(struct st_context *st, const struct st_vertex_program *vp, const struct st_vp_variant *vpv, const struct gl_vertex_array **arrays, struct pipe_vertex_buffer *vbuffer, struct pipe_vertex_element velements[]) { GLuint attr; const GLubyte *low_addr = NULL; GLboolean usingVBO; /* all arrays in a VBO? */ struct gl_buffer_object *bufobj; GLsizei stride; /* Find the lowest address of the arrays we're drawing, * Init bufobj and stride. */ if (vpv->num_inputs) { const struct gl_vertex_array *array; array = get_client_array(vp, arrays, 0); assert(array); /* Since we're doing interleaved arrays, we know there'll be at most * one buffer object and the stride will be the same for all arrays. * Grab them now. */ bufobj = array->BufferObj; stride = array->StrideB; low_addr = arrays[vp->index_to_input[0]]->Ptr; for (attr = 1; attr < vpv->num_inputs; attr++) { const GLubyte *start; array = get_client_array(vp, arrays, attr); if (!array) continue; start = array->Ptr; low_addr = MIN2(low_addr, start); } } else { /* not sure we'll ever have zero inputs, but play it safe */ bufobj = NULL; stride = 0; low_addr = 0; } /* are the arrays in user space? */ usingVBO = _mesa_is_bufferobj(bufobj); for (attr = 0; attr < vpv->num_inputs;) { const struct gl_vertex_array *array; unsigned src_offset; unsigned src_format; array = get_client_array(vp, arrays, attr); assert(array); src_offset = (unsigned) (array->Ptr - low_addr); assert(array->_ElementSize == _mesa_bytes_per_vertex_attrib(array->Size, array->Type)); src_format = st_pipe_vertex_format(array->Type, array->Size, array->Format, array->Normalized, array->Integer); init_velement_lowered(st, vp, velements, src_offset, src_format, array->InstanceDivisor, 0, array->Size, array->Doubles, &attr); } /* * Return the vbuffer info and setup user-space attrib info, if needed. */ if (vpv->num_inputs == 0) { /* just defensive coding here */ vbuffer->buffer = NULL; vbuffer->user_buffer = NULL; vbuffer->buffer_offset = 0; vbuffer->stride = 0; } else if (usingVBO) { /* all interleaved arrays in a VBO */ struct st_buffer_object *stobj = st_buffer_object(bufobj); if (!stobj || !stobj->buffer) { return FALSE; /* out-of-memory error probably */ } vbuffer->buffer = stobj->buffer; vbuffer->user_buffer = NULL; vbuffer->buffer_offset = pointer_to_offset(low_addr); vbuffer->stride = stride; } else { /* all interleaved arrays in user memory */ vbuffer->buffer = NULL; vbuffer->user_buffer = low_addr; vbuffer->buffer_offset = 0; vbuffer->stride = stride; } return TRUE; }
/* Note: detecting the IK chain is duplicate code... in drawarmature.c and in transform_conversions.c */ static void initialize_posetree(struct Object *UNUSED(ob), bPoseChannel *pchan_tip) { bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256], **oldchan; PoseTree *tree; PoseTarget *target; bConstraint *con; bKinematicConstraint *data; int a, segcount= 0, size, newsize, *oldparent, parent; /* find IK constraint, and validate it */ for(con= pchan_tip->constraints.first; con; con= con->next) { if(con->type==CONSTRAINT_TYPE_KINEMATIC) { data=(bKinematicConstraint*)con->data; if (data->flag & CONSTRAINT_IK_AUTO) break; if (data->tar==NULL) continue; if (data->tar->type==OB_ARMATURE && data->subtarget[0]==0) continue; if ((con->flag & (CONSTRAINT_DISABLE|CONSTRAINT_OFF))==0 && (con->enforce!=0.0)) break; } } if(con==NULL) return; /* exclude tip from chain? */ if(!(data->flag & CONSTRAINT_IK_TIP)) pchan_tip= pchan_tip->parent; /* Find the chain's root & count the segments needed */ for (curchan = pchan_tip; curchan; curchan=curchan->parent) { pchan_root = curchan; curchan->flag |= POSE_CHAIN; // don't forget to clear this chanlist[segcount]=curchan; segcount++; if(segcount==data->rootbone || segcount>255) break; // 255 is weak } if (!segcount) return; /* setup the chain data */ /* we make tree-IK, unless all existing targets are in this chain */ for(tree= pchan_root->iktree.first; tree; tree= tree->next) { for(target= tree->targets.first; target; target= target->next) { curchan= tree->pchan[target->tip]; if(curchan->flag & POSE_CHAIN) curchan->flag &= ~POSE_CHAIN; else break; } if(target) break; } /* create a target */ target= MEM_callocN(sizeof(PoseTarget), "posetarget"); target->con= con; pchan_tip->flag &= ~POSE_CHAIN; if(tree==NULL) { /* make new tree */ tree= MEM_callocN(sizeof(PoseTree), "posetree"); tree->type= CONSTRAINT_TYPE_KINEMATIC; tree->iterations= data->iterations; tree->totchannel= segcount; tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH); tree->pchan= MEM_callocN(segcount*sizeof(void*), "ik tree pchan"); tree->parent= MEM_callocN(segcount*sizeof(int), "ik tree parent"); for(a=0; a<segcount; a++) { tree->pchan[a]= chanlist[segcount-a-1]; tree->parent[a]= a-1; } target->tip= segcount-1; /* AND! link the tree to the root */ BLI_addtail(&pchan_root->iktree, tree); } else { tree->iterations= MAX2(data->iterations, tree->iterations); tree->stretch= tree->stretch && !(data->flag & CONSTRAINT_IK_STRETCH); /* skip common pose channels and add remaining*/ size= MIN2(segcount, tree->totchannel); for(a=0; a<size && tree->pchan[a]==chanlist[segcount-a-1]; a++); parent= a-1; segcount= segcount-a; target->tip= tree->totchannel + segcount - 1; if (segcount > 0) { /* resize array */ newsize= tree->totchannel + segcount; oldchan= tree->pchan; oldparent= tree->parent; tree->pchan= MEM_callocN(newsize*sizeof(void*), "ik tree pchan"); tree->parent= MEM_callocN(newsize*sizeof(int), "ik tree parent"); memcpy(tree->pchan, oldchan, sizeof(void*)*tree->totchannel); memcpy(tree->parent, oldparent, sizeof(int)*tree->totchannel); MEM_freeN(oldchan); MEM_freeN(oldparent); /* add new pose channels at the end, in reverse order */ for(a=0; a<segcount; a++) { tree->pchan[tree->totchannel+a]= chanlist[segcount-a-1]; tree->parent[tree->totchannel+a]= tree->totchannel+a-1; } tree->parent[tree->totchannel]= parent; tree->totchannel= newsize; } /* move tree to end of list, for correct evaluation order */ BLI_remlink(&pchan_root->iktree, tree); BLI_addtail(&pchan_root->iktree, tree); } /* add target to the tree */ BLI_addtail(&tree->targets, target); /* mark root channel having an IK tree */ pchan_root->flag |= POSE_IKTREE; }
static int svga_get_param(struct pipe_screen *screen, enum pipe_cap param) { struct svga_screen *svgascreen = svga_screen(screen); struct svga_winsys_screen *sws = svgascreen->sws; SVGA3dDevCapResult result; switch (param) { case PIPE_CAP_NPOT_TEXTURES: case PIPE_CAP_MIXED_FRAMEBUFFER_SIZES: case PIPE_CAP_MIXED_COLOR_DEPTH_BITS: return 1; case PIPE_CAP_TWO_SIDED_STENCIL: return 1; case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: /* * "In virtually every OpenGL implementation and hardware, * GL_MAX_DUAL_SOURCE_DRAW_BUFFERS is 1" * http://www.opengl.org/wiki/Blending */ return sws->have_vgpu10 ? 1 : 0; case PIPE_CAP_ANISOTROPIC_FILTER: return 1; case PIPE_CAP_POINT_SPRITE: return 1; case PIPE_CAP_TGSI_TEXCOORD: return 0; case PIPE_CAP_MAX_RENDER_TARGETS: return svgascreen->max_color_buffers; case PIPE_CAP_OCCLUSION_QUERY: return 1; case PIPE_CAP_QUERY_TIME_ELAPSED: return 0; case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: return sws->have_vgpu10; case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_TEXTURE_SWIZZLE: return 1; case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: return 0; case PIPE_CAP_USER_VERTEX_BUFFERS: case PIPE_CAP_USER_INDEX_BUFFERS: return 0; case PIPE_CAP_USER_CONSTANT_BUFFERS: return 1; case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: return 256; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: { unsigned levels = SVGA_MAX_TEXTURE_LEVELS; if (sws->get_cap(sws, SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH, &result)) levels = MIN2(util_logbase2(result.u) + 1, levels); else levels = 12 /* 2048x2048 */; if (sws->get_cap(sws, SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT, &result)) levels = MIN2(util_logbase2(result.u) + 1, levels); else levels = 12 /* 2048x2048 */; return levels; } case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_VOLUME_EXTENT, &result)) return 8; /* max 128x128x128 */ return MIN2(util_logbase2(result.u) + 1, SVGA_MAX_TEXTURE_LEVELS); case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: /* * No mechanism to query the host, and at least limited to 2048x2048 on * certain hardware. */ return MIN2(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS), 12 /* 2048x2048 */); case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: return sws->have_vgpu10 ? SVGA3D_MAX_SURFACE_ARRAYSIZE : 0; case PIPE_CAP_BLEND_EQUATION_SEPARATE: /* req. for GL 1.5 */ return 1; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: return 1; case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: return sws->have_vgpu10; case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: return 0; case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: return !sws->have_vgpu10; case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: return 1; /* The color outputs of vertex shaders are not clamped */ case PIPE_CAP_VERTEX_COLOR_CLAMPED: return 0; /* The driver can't clamp vertex colors */ case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: return 0; /* The driver can't clamp fragment colors */ case PIPE_CAP_MIXED_COLORBUFFER_FORMATS: return 1; /* expected for GL_ARB_framebuffer_object */ case PIPE_CAP_GLSL_FEATURE_LEVEL: return sws->have_vgpu10 ? 330 : 120; case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: return 0; case PIPE_CAP_SM3: return 1; case PIPE_CAP_DEPTH_CLIP_DISABLE: case PIPE_CAP_INDEP_BLEND_ENABLE: case PIPE_CAP_CONDITIONAL_RENDER: case PIPE_CAP_QUERY_TIMESTAMP: case PIPE_CAP_TGSI_INSTANCEID: case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: case PIPE_CAP_SEAMLESS_CUBE_MAP: case PIPE_CAP_FAKE_SW_MSAA: return sws->have_vgpu10; case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS: return sws->have_vgpu10 ? SVGA3D_DX_MAX_SOTARGETS : 0; case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: return sws->have_vgpu10 ? 4 : 0; case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: return sws->have_vgpu10 ? SVGA3D_MAX_STREAMOUT_DECLS : 0; case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS: return 0; case PIPE_CAP_TEXTURE_MULTISAMPLE: return svgascreen->ms_samples ? 1 : 0; case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE: return SVGA3D_DX_MAX_RESOURCE_SIZE; case PIPE_CAP_MIN_TEXEL_OFFSET: return sws->have_vgpu10 ? VGPU10_MIN_TEXEL_FETCH_OFFSET : 0; case PIPE_CAP_MAX_TEXEL_OFFSET: return sws->have_vgpu10 ? VGPU10_MAX_TEXEL_FETCH_OFFSET : 0; case PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET: case PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET: return 0; case PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES: return sws->have_vgpu10 ? 256 : 0; case PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS: return sws->have_vgpu10 ? 1024 : 0; case PIPE_CAP_PRIMITIVE_RESTART: return 1; /* may be a sw fallback, depending on restart index */ case PIPE_CAP_GENERATE_MIPMAP: return sws->have_generate_mipmap_cmd; /* Unsupported features */ case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION: case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: case PIPE_CAP_INDEP_BLEND_FUNC: case PIPE_CAP_TEXTURE_BARRIER: case PIPE_CAP_MAX_VERTEX_STREAMS: case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: case PIPE_CAP_COMPUTE: case PIPE_CAP_START_INSTANCE: case PIPE_CAP_CUBE_MAP_ARRAY: case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_QUERY_PIPELINE_STATISTICS: case PIPE_CAP_TGSI_VS_LAYER_VIEWPORT: case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: case PIPE_CAP_TEXTURE_GATHER_SM5: case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: 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_DRAW_INDIRECT: case PIPE_CAP_MULTI_DRAW_INDIRECT: case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS: case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE: case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: case PIPE_CAP_SAMPLER_VIEW_TARGET: case PIPE_CAP_CLIP_HALFZ: case PIPE_CAP_VERTEXID_NOBASE: case PIPE_CAP_POLYGON_OFFSET_CLAMP: case PIPE_CAP_MULTISAMPLE_Z_RESOLVE: case PIPE_CAP_TGSI_PACK_HALF_FLOAT: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: case PIPE_CAP_STRING_MARKER: case PIPE_CAP_SURFACE_REINTERPRET_BLOCKS: case PIPE_CAP_QUERY_MEMORY_INFO: case PIPE_CAP_PCI_GROUP: case PIPE_CAP_PCI_BUS: case PIPE_CAP_PCI_DEVICE: case PIPE_CAP_PCI_FUNCTION: case PIPE_CAP_ROBUST_BUFFER_ACCESS_BEHAVIOR: return 0; case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: return 64; case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: return 1; /* need 4-byte alignment for all offsets and strides */ case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE: return 2048; case PIPE_CAP_MAX_VIEWPORTS: return 1; case PIPE_CAP_ENDIANNESS: return PIPE_ENDIAN_LITTLE; case PIPE_CAP_VENDOR_ID: return 0x15ad; /* VMware Inc. */ case PIPE_CAP_DEVICE_ID: return 0x0405; /* assume SVGA II */ case PIPE_CAP_ACCELERATED: return 0; /* XXX: */ case PIPE_CAP_VIDEO_MEMORY: /* XXX: Query the host ? */ return 1; case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS: return sws->have_vgpu10; case PIPE_CAP_CLEAR_TEXTURE: return sws->have_vgpu10; case PIPE_CAP_UMA: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS: 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_FORCE_PERSAMPLE_INTERP: case PIPE_CAP_SHAREABLE_SHADERS: case PIPE_CAP_DRAW_PARAMETERS: case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL: case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY: case PIPE_CAP_QUERY_BUFFER_OBJECT: case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT: case PIPE_CAP_CULL_DISTANCE: case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES: case PIPE_CAP_TGSI_VOTE: case PIPE_CAP_MAX_WINDOW_RECTANGLES: case PIPE_CAP_POLYGON_OFFSET_UNITS_UNSCALED: case PIPE_CAP_VIEWPORT_SUBPIXEL_BITS: case PIPE_CAP_TGSI_ARRAY_COMPONENTS: return 0; } debug_printf("Unexpected PIPE_CAP_ query %u\n", param); return 0; }
int Read_EntryProc_Config( config_file_t config, void *module_config, char *msg_out, int for_reload ) { int rc, blc_index, i; int tmpval; entry_proc_config_t *conf = ( entry_proc_config_t * ) module_config; char pipeline_names[PIPELINE_STAGE_COUNT][256]; char *entry_proc_allowed[PIPELINE_STAGE_COUNT + 5]; entry_proc_allowed[0] = "nb_threads"; entry_proc_allowed[1] = "max_pending_operations"; entry_proc_allowed[2] = "match_classes"; entry_proc_allowed[3] = ALERT_BLOCK; entry_proc_allowed[PIPELINE_STAGE_COUNT + 4] = NULL; /* PIPELINE_STAGE_COUNT+4 = last slot */ /* get EntryProcessor block */ config_item_t entryproc_block = rh_config_FindItemByName( config, ENTRYPROC_CONFIG_BLOCK ); if ( entryproc_block == NULL ) { strcpy( msg_out, "Missing configuration block '" ENTRYPROC_CONFIG_BLOCK "'" ); /* No error because no parameter is mandatory */ return 0; } if ( rh_config_ItemType( entryproc_block ) != CONFIG_ITEM_BLOCK ) { strcpy( msg_out, "A block is expected for '" ENTRYPROC_CONFIG_BLOCK "' item" ); return EINVAL; } /* retrieve parameters */ rc = GetIntParam( entryproc_block, ENTRYPROC_CONFIG_BLOCK, "nb_threads", INT_PARAM_POSITIVE | INT_PARAM_NOT_NULL, ( int * ) &conf->nb_thread, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; rc = GetIntParam( entryproc_block, ENTRYPROC_CONFIG_BLOCK, "max_pending_operations", INT_PARAM_POSITIVE, ( int * ) &conf->max_pending_operations, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; rc = GetBoolParam( entryproc_block, ENTRYPROC_CONFIG_BLOCK, "match_classes", 0, &conf->match_classes, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; /* look for '<stage>_thread_max' parameters */ for ( i = 0; i < PIPELINE_STAGE_COUNT; i++ ) { char varname[256]; snprintf( varname, 256, "%s_threads_max", entry_proc_pipeline[i].stage_name ); strncpy( pipeline_names[i], varname, 256 ); entry_proc_allowed[i + 4] = pipeline_names[i]; rc = GetIntParam( entryproc_block, ENTRYPROC_CONFIG_BLOCK, varname, INT_PARAM_POSITIVE, &tmpval, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; else if ( ( rc != ENOENT ) && ( tmpval > 0 ) ) /* 0: keep default */ { if ( entry_proc_pipeline[i].stage_flags & STAGE_FLAG_MAX_THREADS ) entry_proc_pipeline[i].max_thread_count = MIN2( entry_proc_pipeline[i].max_thread_count, tmpval ); else if ( entry_proc_pipeline[i].stage_flags & STAGE_FLAG_PARALLEL ) { /* the stqge is no more parallel, it has a limited number of threads */ entry_proc_pipeline[i].stage_flags &= ~STAGE_FLAG_PARALLEL; entry_proc_pipeline[i].stage_flags |= STAGE_FLAG_MAX_THREADS; entry_proc_pipeline[i].max_thread_count = tmpval; } else if ( ( entry_proc_pipeline[i].stage_flags & STAGE_FLAG_SEQUENTIAL ) && ( tmpval != 1 ) ) { sprintf( msg_out, "%s is sequential. Cannot use %u threads at this stage.", entry_proc_pipeline[i].stage_name, tmpval ); return EINVAL; } } } /* Find and parse "Alert" blocks */ for ( blc_index = 0; blc_index < rh_config_GetNbItems( entryproc_block ); blc_index++ ) { char *block_name; config_item_t curr_item = rh_config_GetItemByIndex( entryproc_block, blc_index ); critical_err_check( curr_item, ENTRYPROC_CONFIG_BLOCK ); if ( rh_config_ItemType( curr_item ) != CONFIG_ITEM_BLOCK ) continue; block_name = rh_config_GetBlockName( curr_item ); critical_err_check( curr_item, ENTRYPROC_CONFIG_BLOCK ); if ( !strcasecmp( block_name, ALERT_BLOCK ) ) { char * alert_title = NULL; if ( conf->alert_count == 0 ) conf->alert_list = ( alert_item_t * ) malloc( sizeof( alert_item_t ) ); else conf->alert_list = ( alert_item_t * ) realloc( conf->alert_list, ( conf->alert_count + 1 ) * sizeof( alert_item_t ) ); conf->alert_count++; alert_title = rh_config_GetBlockId( curr_item ); if ( alert_title != NULL ) strncpy( conf->alert_list[conf->alert_count - 1].title, alert_title, ALERT_TITLE_MAX ); else conf->alert_list[conf->alert_count - 1].title[0] = '\0'; /* analyze boolean expression */ rc = GetBoolExpr( curr_item, block_name, &conf->alert_list[conf->alert_count - 1].boolexpr, &conf->alert_list[conf->alert_count - 1].attr_mask, msg_out ); if ( rc ) return rc; conf->alert_attr_mask |= conf->alert_list[conf->alert_count - 1].attr_mask; } } /* Loop on subblocks */ CheckUnknownParameters( entryproc_block, ENTRYPROC_CONFIG_BLOCK, ( const char ** ) entry_proc_allowed ); return 0; }
static int vgpu9_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param) { struct svga_screen *svgascreen = svga_screen(screen); struct svga_winsys_screen *sws = svgascreen->sws; unsigned val; assert(!sws->have_vgpu10); switch (shader) { case PIPE_SHADER_FRAGMENT: switch (param) { case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: return get_uint_cap(sws, SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS, 512); case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: return 512; case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: return SVGA3D_MAX_NESTING_LEVEL; case PIPE_SHADER_CAP_MAX_INPUTS: return 10; case PIPE_SHADER_CAP_MAX_OUTPUTS: return svgascreen->max_color_buffers; case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: return 224 * sizeof(float[4]); case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: return 1; case PIPE_SHADER_CAP_MAX_TEMPS: val = get_uint_cap(sws, SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS, 32); return MIN2(val, SVGA3D_TEMPREG_MAX); case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: /* * Although PS 3.0 has some addressing abilities it can only represent * loops that can be statically determined and unrolled. Given we can * only handle a subset of the cases that the state tracker already * does it is better to defer loop unrolling to the state tracker. */ return 0; case PIPE_SHADER_CAP_MAX_PREDS: return 1; case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: return 0; case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED: return 0; case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 0; case PIPE_SHADER_CAP_SUBROUTINES: return 0; case PIPE_SHADER_CAP_INTEGERS: return 0; case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS: return 16; case PIPE_SHADER_CAP_PREFERRED_IR: return PIPE_SHADER_IR_TGSI; case PIPE_SHADER_CAP_SUPPORTED_IRS: return 0; case PIPE_SHADER_CAP_DOUBLES: case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED: case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED: case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED: case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE: case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS: case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: return 0; case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT: return 32; } /* If we get here, we failed to handle a cap above */ debug_printf("Unexpected fragment shader query %u\n", param); return 0; case PIPE_SHADER_VERTEX: switch (param) { case PIPE_SHADER_CAP_MAX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS: return get_uint_cap(sws, SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS, 512); case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS: case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS: /* XXX: until we have vertex texture support */ return 0; case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH: return SVGA3D_MAX_NESTING_LEVEL; case PIPE_SHADER_CAP_MAX_INPUTS: return 16; case PIPE_SHADER_CAP_MAX_OUTPUTS: return 10; case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: return 256 * sizeof(float[4]); case PIPE_SHADER_CAP_MAX_CONST_BUFFERS: return 1; case PIPE_SHADER_CAP_MAX_TEMPS: val = get_uint_cap(sws, SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS, 32); return MIN2(val, SVGA3D_TEMPREG_MAX); case PIPE_SHADER_CAP_MAX_PREDS: return 1; case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED: return 0; case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED: return 0; case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR: case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR: return 1; case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR: return 0; case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR: return 1; case PIPE_SHADER_CAP_SUBROUTINES: return 0; case PIPE_SHADER_CAP_INTEGERS: return 0; case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS: case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS: return 0; case PIPE_SHADER_CAP_PREFERRED_IR: return PIPE_SHADER_IR_TGSI; case PIPE_SHADER_CAP_SUPPORTED_IRS: return 0; case PIPE_SHADER_CAP_DOUBLES: case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED: case PIPE_SHADER_CAP_TGSI_DFRACEXP_DLDEXP_SUPPORTED: case PIPE_SHADER_CAP_TGSI_FMA_SUPPORTED: case PIPE_SHADER_CAP_TGSI_ANY_INOUT_DECL_RANGE: case PIPE_SHADER_CAP_MAX_SHADER_BUFFERS: case PIPE_SHADER_CAP_MAX_SHADER_IMAGES: return 0; case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT: return 32; } /* If we get here, we failed to handle a cap above */ debug_printf("Unexpected vertex shader query %u\n", param); return 0; case PIPE_SHADER_GEOMETRY: case PIPE_SHADER_COMPUTE: case PIPE_SHADER_TESS_CTRL: case PIPE_SHADER_TESS_EVAL: /* no support for geometry, tess or compute shaders at this time */ return 0; default: debug_printf("Unexpected shader type (%u) query\n", shader); return 0; } return 0; }
MethodLiveness::MethodLiveness(Arena* arena, ciMethod* method) : _bci_block_start((uintptr_t*)arena->Amalloc((method->code_size() >> LogBitsPerByte) + 1), method->code_size()) { _arena = arena; _method = method; _bit_map_size_bits = method->max_locals(); _bit_map_size_words = (_bit_map_size_bits / sizeof(unsigned int)) + 1; _bci_block_start.clear(); } void MethodLiveness::compute_liveness() { #ifndef PRODUCT if (TraceLivenessGen) { tty->print_cr("################################################################"); tty->print("# Computing liveness information for "); method()->print_short_name(); } if (TimeLivenessAnalysis) _time_total.start(); #endif { TraceTime buildGraph(NULL, &_time_build_graph, TimeLivenessAnalysis); init_basic_blocks(); } { TraceTime genKill(NULL, &_time_gen_kill, TimeLivenessAnalysis); init_gen_kill(); } { TraceTime flow(NULL, &_time_flow, TimeLivenessAnalysis); propagate_liveness(); } #ifndef PRODUCT if (TimeLivenessAnalysis) _time_total.stop(); if (TimeLivenessAnalysis) { // Collect statistics _total_bytes += method()->code_size(); _total_methods++; int num_blocks = _block_count; _total_blocks += num_blocks; _max_method_blocks = MAX2(num_blocks,_max_method_blocks); for (int i=0; i<num_blocks; i++) { BasicBlock *block = _block_list[i]; int numEdges = block->_normal_predecessors->length(); int numExcEdges = block->_exception_predecessors->length(); _total_edges += numEdges; _total_exc_edges += numExcEdges; _max_block_edges = MAX2(numEdges,_max_block_edges); _max_block_exc_edges = MAX2(numExcEdges,_max_block_exc_edges); } int numLocals = _bit_map_size_bits; _total_method_locals += numLocals; _max_method_locals = MAX2(numLocals,_max_method_locals); } #endif } void MethodLiveness::init_basic_blocks() { bool bailout = false; int method_len = method()->code_size(); ciMethodBlocks *mblocks = method()->get_method_blocks(); // Create an array to store the bci->BasicBlock mapping. _block_map = new (arena()) GrowableArray<BasicBlock*>(arena(), method_len, method_len, NULL); _block_count = mblocks->num_blocks(); _block_list = (BasicBlock **) arena()->Amalloc(sizeof(BasicBlock *) * _block_count); // Used for patching up jsr/ret control flow. GrowableArray<BasicBlock*>* jsr_exit_list = new GrowableArray<BasicBlock*>(5); GrowableArray<BasicBlock*>* ret_list = new GrowableArray<BasicBlock*>(5); // generate our block list from ciMethodBlocks for (int blk = 0; blk < _block_count; blk++) { ciBlock *cib = mblocks->block(blk); int start_bci = cib->start_bci(); _block_list[blk] = new (arena()) BasicBlock(this, start_bci, cib->limit_bci()); _block_map->at_put(start_bci, _block_list[blk]); // mark all bcis where a new basic block starts _bci_block_start.set_bit(start_bci); } // fill in the predecessors of blocks ciBytecodeStream bytes(method()); for (int blk = 0; blk < _block_count; blk++) { BasicBlock *current_block = _block_list[blk]; int bci = mblocks->block(blk)->control_bci(); if (bci == ciBlock::fall_through_bci) { int limit = current_block->limit_bci(); if (limit < method_len) { BasicBlock *next = _block_map->at(limit); assert( next != NULL, "must be a block immediately following this one."); next->add_normal_predecessor(current_block); } continue; } bytes.reset_to_bci(bci); Bytecodes::Code code = bytes.next(); BasicBlock *dest; // Now we need to interpret the instruction's effect // on control flow. assert (current_block != NULL, "we must have a current block"); switch (code) { case Bytecodes::_ifeq: case Bytecodes::_ifne: case Bytecodes::_iflt: case Bytecodes::_ifge: case Bytecodes::_ifgt: case Bytecodes::_ifle: case Bytecodes::_if_icmpeq: case Bytecodes::_if_icmpne: case Bytecodes::_if_icmplt: case Bytecodes::_if_icmpge: case Bytecodes::_if_icmpgt: case Bytecodes::_if_icmple: case Bytecodes::_if_acmpeq: case Bytecodes::_if_acmpne: case Bytecodes::_ifnull: case Bytecodes::_ifnonnull: // Two way branch. Set predecessors at each destination. dest = _block_map->at(bytes.next_bci()); assert(dest != NULL, "must be a block immediately following this one."); dest->add_normal_predecessor(current_block); dest = _block_map->at(bytes.get_dest()); assert(dest != NULL, "branch desination must start a block."); dest->add_normal_predecessor(current_block); break; case Bytecodes::_goto: dest = _block_map->at(bytes.get_dest()); assert(dest != NULL, "branch desination must start a block."); dest->add_normal_predecessor(current_block); break; case Bytecodes::_goto_w: dest = _block_map->at(bytes.get_far_dest()); assert(dest != NULL, "branch desination must start a block."); dest->add_normal_predecessor(current_block); break; case Bytecodes::_tableswitch: { Bytecode_tableswitch *tableswitch = Bytecode_tableswitch_at(bytes.cur_bcp()); int len = tableswitch->length(); dest = _block_map->at(bci + tableswitch->default_offset()); assert(dest != NULL, "branch desination must start a block."); dest->add_normal_predecessor(current_block); while (--len >= 0) { dest = _block_map->at(bci + tableswitch->dest_offset_at(len)); assert(dest != NULL, "branch desination must start a block."); dest->add_normal_predecessor(current_block); } break; } case Bytecodes::_lookupswitch: { Bytecode_lookupswitch *lookupswitch = Bytecode_lookupswitch_at(bytes.cur_bcp()); int npairs = lookupswitch->number_of_pairs(); dest = _block_map->at(bci + lookupswitch->default_offset()); assert(dest != NULL, "branch desination must start a block."); dest->add_normal_predecessor(current_block); while(--npairs >= 0) { LookupswitchPair *pair = lookupswitch->pair_at(npairs); dest = _block_map->at( bci + pair->offset()); assert(dest != NULL, "branch desination must start a block."); dest->add_normal_predecessor(current_block); } break; } case Bytecodes::_jsr: { assert(bytes.is_wide()==false, "sanity check"); dest = _block_map->at(bytes.get_dest()); assert(dest != NULL, "branch desination must start a block."); dest->add_normal_predecessor(current_block); BasicBlock *jsrExit = _block_map->at(current_block->limit_bci()); assert(jsrExit != NULL, "jsr return bci must start a block."); jsr_exit_list->append(jsrExit); break; } case Bytecodes::_jsr_w: { dest = _block_map->at(bytes.get_far_dest()); assert(dest != NULL, "branch desination must start a block."); dest->add_normal_predecessor(current_block); BasicBlock *jsrExit = _block_map->at(current_block->limit_bci()); assert(jsrExit != NULL, "jsr return bci must start a block."); jsr_exit_list->append(jsrExit); break; } case Bytecodes::_wide: assert(false, "wide opcodes should not be seen here"); break; case Bytecodes::_athrow: case Bytecodes::_ireturn: case Bytecodes::_lreturn: case Bytecodes::_freturn: case Bytecodes::_dreturn: case Bytecodes::_areturn: case Bytecodes::_return: // These opcodes are not the normal predecessors of any other opcodes. break; case Bytecodes::_ret: // We will patch up jsr/rets in a subsequent pass. ret_list->append(current_block); break; case Bytecodes::_breakpoint: // Bail out of there are breakpoints in here. bailout = true; break; default: // Do nothing. break; } } // Patch up the jsr/ret's. We conservatively assume that any ret // can return to any jsr site. int ret_list_len = ret_list->length(); int jsr_exit_list_len = jsr_exit_list->length(); if (ret_list_len > 0 && jsr_exit_list_len > 0) { for (int i = jsr_exit_list_len - 1; i >= 0; i--) { BasicBlock *jsrExit = jsr_exit_list->at(i); for (int i = ret_list_len - 1; i >= 0; i--) { jsrExit->add_normal_predecessor(ret_list->at(i)); } } } // Compute exception edges. for (int b=_block_count-1; b >= 0; b--) { BasicBlock *block = _block_list[b]; int block_start = block->start_bci(); int block_limit = block->limit_bci(); ciExceptionHandlerStream handlers(method()); for (; !handlers.is_done(); handlers.next()) { ciExceptionHandler* handler = handlers.handler(); int start = handler->start(); int limit = handler->limit(); int handler_bci = handler->handler_bci(); int intersect_start = MAX2(block_start, start); int intersect_limit = MIN2(block_limit, limit); if (intersect_start < intersect_limit) { // The catch range has a nonempty intersection with this // basic block. That means this basic block can be an // exceptional predecessor. _block_map->at(handler_bci)->add_exception_predecessor(block); if (handler->is_catch_all()) { // This is a catch-all block. if (intersect_start == block_start && intersect_limit == block_limit) { // The basic block is entirely contained in this catch-all block. // Skip the rest of the exception handlers -- they can never be // reached in execution. break; } } } } } }
/** * Create a new svga_screen object */ struct pipe_screen * svga_screen_create(struct svga_winsys_screen *sws) { struct svga_screen *svgascreen; struct pipe_screen *screen; #ifdef DEBUG SVGA_DEBUG = debug_get_flags_option("SVGA_DEBUG", svga_debug_flags, 0 ); #endif svgascreen = CALLOC_STRUCT(svga_screen); if (!svgascreen) goto error1; svgascreen->debug.force_level_surface_view = debug_get_bool_option("SVGA_FORCE_LEVEL_SURFACE_VIEW", FALSE); svgascreen->debug.force_surface_view = debug_get_bool_option("SVGA_FORCE_SURFACE_VIEW", FALSE); svgascreen->debug.force_sampler_view = debug_get_bool_option("SVGA_FORCE_SAMPLER_VIEW", FALSE); svgascreen->debug.no_surface_view = debug_get_bool_option("SVGA_NO_SURFACE_VIEW", FALSE); svgascreen->debug.no_sampler_view = debug_get_bool_option("SVGA_NO_SAMPLER_VIEW", FALSE); svgascreen->debug.no_cache_index_buffers = debug_get_bool_option("SVGA_NO_CACHE_INDEX_BUFFERS", FALSE); screen = &svgascreen->screen; screen->destroy = svga_destroy_screen; screen->get_name = svga_get_name; screen->get_vendor = svga_get_vendor; screen->get_device_vendor = svga_get_vendor; // TODO actual device vendor screen->get_param = svga_get_param; screen->get_shader_param = svga_get_shader_param; screen->get_paramf = svga_get_paramf; screen->get_timestamp = NULL; screen->is_format_supported = svga_is_format_supported; screen->context_create = svga_context_create; screen->fence_reference = svga_fence_reference; screen->fence_finish = svga_fence_finish; screen->get_driver_query_info = svga_get_driver_query_info; svgascreen->sws = sws; svga_init_screen_resource_functions(svgascreen); if (sws->get_hw_version) { svgascreen->hw_version = sws->get_hw_version(sws); } else { svgascreen->hw_version = SVGA3D_HWVERSION_WS65_B1; } /* * The D16, D24X8, and D24S8 formats always do an implicit shadow compare * when sampled from, where as the DF16, DF24, and D24S8_INT do not. So * we prefer the later when available. * * This mimics hardware vendors extensions for D3D depth sampling. See also * http://aras-p.info/texts/D3D9GPUHacks.html */ { boolean has_df16, has_df24, has_d24s8_int; SVGA3dSurfaceFormatCaps caps; SVGA3dSurfaceFormatCaps mask; mask.value = 0; mask.zStencil = 1; mask.texture = 1; svgascreen->depth.z16 = SVGA3D_Z_D16; svgascreen->depth.x8z24 = SVGA3D_Z_D24X8; svgascreen->depth.s8z24 = SVGA3D_Z_D24S8; svga_get_format_cap(svgascreen, SVGA3D_Z_DF16, &caps); has_df16 = (caps.value & mask.value) == mask.value; svga_get_format_cap(svgascreen, SVGA3D_Z_DF24, &caps); has_df24 = (caps.value & mask.value) == mask.value; svga_get_format_cap(svgascreen, SVGA3D_Z_D24S8_INT, &caps); has_d24s8_int = (caps.value & mask.value) == mask.value; /* XXX: We might want some other logic here. * Like if we only have d24s8_int we should * emulate the other formats with that. */ if (has_df16) { svgascreen->depth.z16 = SVGA3D_Z_DF16; } if (has_df24) { svgascreen->depth.x8z24 = SVGA3D_Z_DF24; } if (has_d24s8_int) { svgascreen->depth.s8z24 = SVGA3D_Z_D24S8_INT; } } /* Query device caps */ if (sws->have_vgpu10) { svgascreen->haveProvokingVertex = get_bool_cap(sws, SVGA3D_DEVCAP_DX_PROVOKING_VERTEX, FALSE); svgascreen->haveLineSmooth = TRUE; svgascreen->maxPointSize = 80.0F; svgascreen->max_color_buffers = SVGA3D_DX_MAX_RENDER_TARGETS; /* Multisample samples per pixel */ if (debug_get_bool_option("SVGA_MSAA", TRUE)) { svgascreen->ms_samples = get_uint_cap(sws, SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES, 0); } /* Maximum number of constant buffers */ svgascreen->max_const_buffers = get_uint_cap(sws, SVGA3D_DEVCAP_DX_MAX_CONSTANT_BUFFERS, 1); assert(svgascreen->max_const_buffers <= SVGA_MAX_CONST_BUFS); } else { /* VGPU9 */ unsigned vs_ver = get_uint_cap(sws, SVGA3D_DEVCAP_VERTEX_SHADER_VERSION, SVGA3DVSVERSION_NONE); unsigned fs_ver = get_uint_cap(sws, SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION, SVGA3DPSVERSION_NONE); /* we require Shader model 3.0 or later */ if (fs_ver < SVGA3DPSVERSION_30 || vs_ver < SVGA3DVSVERSION_30) { goto error2; } svgascreen->haveProvokingVertex = FALSE; svgascreen->haveLineSmooth = get_bool_cap(sws, SVGA3D_DEVCAP_LINE_AA, FALSE); svgascreen->maxPointSize = get_float_cap(sws, SVGA3D_DEVCAP_MAX_POINT_SIZE, 1.0f); /* Keep this to a reasonable size to avoid failures in conform/pntaa.c */ svgascreen->maxPointSize = MIN2(svgascreen->maxPointSize, 80.0f); /* The SVGA3D device always supports 4 targets at this time, regardless * of what querying SVGA3D_DEVCAP_MAX_RENDER_TARGETS might return. */ svgascreen->max_color_buffers = 4; /* Only support one constant buffer */ svgascreen->max_const_buffers = 1; /* No multisampling */ svgascreen->ms_samples = 0; } /* common VGPU9 / VGPU10 caps */ svgascreen->haveLineStipple = get_bool_cap(sws, SVGA3D_DEVCAP_LINE_STIPPLE, FALSE); svgascreen->maxLineWidth = get_float_cap(sws, SVGA3D_DEVCAP_MAX_LINE_WIDTH, 1.0f); svgascreen->maxLineWidthAA = get_float_cap(sws, SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH, 1.0f); if (0) { debug_printf("svga: haveProvokingVertex %u\n", svgascreen->haveProvokingVertex); debug_printf("svga: haveLineStip %u " "haveLineSmooth %u maxLineWidth %f\n", svgascreen->haveLineStipple, svgascreen->haveLineSmooth, svgascreen->maxLineWidth); debug_printf("svga: maxPointSize %g\n", svgascreen->maxPointSize); debug_printf("svga: msaa samples mask: 0x%x\n", svgascreen->ms_samples); } pipe_mutex_init(svgascreen->tex_mutex); pipe_mutex_init(svgascreen->swc_mutex); svga_screen_cache_init(svgascreen); return screen; error2: FREE(svgascreen); error1: return NULL; }
/* * Helper function called from _swrast_write_zoomed_rgba/rgb/index_span(). */ static void zoom_span( GLcontext *ctx, const struct sw_span *span, const GLvoid *src, GLint y0, GLenum format, GLint skipPixels ) { GLint r0, r1, row; GLint c0, c1, skipCol; GLint i, j; const GLuint maxWidth = MIN2( ctx->DrawBuffer->Width, MAX_WIDTH ); struct sw_span zoomed; struct span_arrays zoomed_arrays; /* this is big! */ /* no pixel arrays! must be horizontal spans. */ ASSERT((span->arrayMask & SPAN_XY) == 0); ASSERT(span->primitive == GL_BITMAP); INIT_SPAN(zoomed, GL_BITMAP, 0, 0, 0); zoomed.array = &zoomed_arrays; /* copy fog interp info */ zoomed.fog = span->fog; zoomed.fogStep = span->fogStep; /* XXX copy texcoord info? */ if (format == GL_RGBA || format == GL_RGB) { /* copy Z info */ zoomed.z = span->z; zoomed.zStep = span->zStep; /* we'll generate an array of colorss */ zoomed.interpMask = span->interpMask & ~SPAN_RGBA; zoomed.arrayMask |= SPAN_RGBA; } else if (format == GL_COLOR_INDEX) { /* copy Z info */ zoomed.z = span->z; zoomed.zStep = span->zStep; /* we'll generate an array of color indexes */ zoomed.interpMask = span->interpMask & ~SPAN_INDEX; zoomed.arrayMask |= SPAN_INDEX; } else { assert(format == GL_DEPTH_COMPONENT); /* Copy color info */ zoomed.red = span->red; zoomed.green = span->green; zoomed.blue = span->blue; zoomed.alpha = span->alpha; zoomed.redStep = span->redStep; zoomed.greenStep = span->greenStep; zoomed.blueStep = span->blueStep; zoomed.alphaStep = span->alphaStep; /* we'll generate an array of depth values */ zoomed.interpMask = span->interpMask & ~SPAN_Z; zoomed.arrayMask |= SPAN_Z; } /* * Compute which columns to draw: [c0, c1) */ c0 = (GLint) (span->x + skipPixels * ctx->Pixel.ZoomX); c1 = (GLint) (span->x + (skipPixels + span->end) * ctx->Pixel.ZoomX); if (c0 == c1) { return; } else if (c1 < c0) { /* swap */ GLint ctmp = c1; c1 = c0; c0 = ctmp; } if (c0 < 0) { zoomed.x = 0; zoomed.start = 0; zoomed.end = c1; skipCol = -c0; } else { zoomed.x = c0; zoomed.start = 0; zoomed.end = c1 - c0; skipCol = 0; } if (zoomed.end > maxWidth) zoomed.end = maxWidth; /* * Compute which rows to draw: [r0, r1) */ row = span->y - y0; r0 = y0 + (GLint) (row * ctx->Pixel.ZoomY); r1 = y0 + (GLint) ((row+1) * ctx->Pixel.ZoomY); if (r0 == r1) { return; } else if (r1 < r0) { /* swap */ GLint rtmp = r1; r1 = r0; r0 = rtmp; } ASSERT(r0 < r1); ASSERT(c0 < c1); /* * Trivial clip rejection testing. */ if (r1 < 0) /* below window */ return; if (r0 >= (GLint) ctx->DrawBuffer->Height) /* above window */ return; if (c1 < 0) /* left of window */ return; if (c0 >= (GLint) ctx->DrawBuffer->Width) /* right of window */ return; /* zoom the span horizontally */ if (format == GL_RGBA) { const GLchan (*rgba)[4] = (const GLchan (*)[4]) src; if (ctx->Pixel.ZoomX == -1.0F) { /* common case */ for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = span->end - (j + skipCol) - 1; COPY_CHAN4(zoomed.array->rgba[j], rgba[i]); } } else { /* general solution */ const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = (GLint) ((j + skipCol) * xscale); if (ctx->Pixel.ZoomX < 0.0) { ASSERT(i <= 0); i = span->end + i - 1; } ASSERT(i >= 0); ASSERT(i < (GLint) span->end); COPY_CHAN4(zoomed.array->rgba[j], rgba[i]); } } } else if (format == GL_RGB) { const GLchan (*rgb)[3] = (const GLchan (*)[3]) src; if (ctx->Pixel.ZoomX == -1.0F) { /* common case */ for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = span->end - (j + skipCol) - 1; zoomed.array->rgba[j][0] = rgb[i][0]; zoomed.array->rgba[j][1] = rgb[i][1]; zoomed.array->rgba[j][2] = rgb[i][2]; zoomed.array->rgba[j][3] = CHAN_MAX; } } else { /* general solution */ const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = (GLint) ((j + skipCol) * xscale); if (ctx->Pixel.ZoomX < 0.0) { ASSERT(i <= 0); i = span->end + i - 1; } ASSERT(i >= 0); ASSERT(i < (GLint) span->end); zoomed.array->rgba[j][0] = rgb[i][0]; zoomed.array->rgba[j][1] = rgb[i][1]; zoomed.array->rgba[j][2] = rgb[i][2]; zoomed.array->rgba[j][3] = CHAN_MAX; } } } else if (format == GL_COLOR_INDEX) { const GLuint *indexes = (const GLuint *) src; if (ctx->Pixel.ZoomX == -1.0F) { /* common case */ for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = span->end - (j + skipCol) - 1; zoomed.array->index[j] = indexes[i]; } } else { /* general solution */ const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = (GLint) ((j + skipCol) * xscale); if (ctx->Pixel.ZoomX < 0.0) { ASSERT(i <= 0); i = span->end + i - 1; } ASSERT(i >= 0); ASSERT(i < (GLint) span->end); zoomed.array->index[j] = indexes[i]; } } } else { const GLdepth *zValues = (const GLuint *) src; assert(format == GL_DEPTH_COMPONENT); if (ctx->Pixel.ZoomX == -1.0F) { /* common case */ for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = span->end - (j + skipCol) - 1; zoomed.array->z[j] = zValues[i]; } } else { /* general solution */ const GLfloat xscale = 1.0F / ctx->Pixel.ZoomX; for (j = (GLint) zoomed.start; j < (GLint) zoomed.end; j++) { i = (GLint) ((j + skipCol) * xscale); if (ctx->Pixel.ZoomX < 0.0) { ASSERT(i <= 0); i = span->end + i - 1; } ASSERT(i >= 0); ASSERT(i < (GLint) span->end); zoomed.array->z[j] = zValues[i]; } } /* Now, fall into either the RGB or COLOR_INDEX path below */ if (ctx->Visual.rgbMode) format = GL_RGBA; else format = GL_COLOR_INDEX; } /* write the span in rows [r0, r1) */ if (format == GL_RGBA || format == GL_RGB) { /* Writing the span may modify the colors, so make a backup now if we're * going to call _swrast_write_zoomed_span() more than once. * Also, clipping may change the span end value, so store it as well. */ GLchan rgbaSave[MAX_WIDTH][4]; const GLint end = zoomed.end; /* save */ if (r1 - r0 > 1) { MEMCPY(rgbaSave, zoomed.array->rgba, zoomed.end * 4 * sizeof(GLchan)); } for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) { _swrast_write_rgba_span(ctx, &zoomed); zoomed.end = end; /* restore */ if (r1 - r0 > 1) { /* restore the colors */ MEMCPY(zoomed.array->rgba, rgbaSave, zoomed.end*4 * sizeof(GLchan)); } } } else if (format == GL_COLOR_INDEX) { GLuint indexSave[MAX_WIDTH]; const GLint end = zoomed.end; /* save */ if (r1 - r0 > 1) { MEMCPY(indexSave, zoomed.array->index, zoomed.end * sizeof(GLuint)); } for (zoomed.y = r0; zoomed.y < r1; zoomed.y++) { _swrast_write_index_span(ctx, &zoomed); zoomed.end = end; /* restore */ if (r1 - r0 > 1) { /* restore the colors */ MEMCPY(zoomed.array->index, indexSave, zoomed.end * sizeof(GLuint)); } } } }
/** * Examine a texture object to determine if it is complete. * * The gl_texture_object::Complete flag will be set to GL_TRUE or GL_FALSE * accordingly. * * \param ctx GL context. * \param t texture object. * * According to the texture target, verifies that each of the mipmaps is * present and has the expected size. */ void _mesa_test_texobj_completeness( const GLcontext *ctx, struct gl_texture_object *t ) { const GLint baseLevel = t->BaseLevel; GLint maxLog2 = 0, maxLevels = 0; t->Complete = GL_TRUE; /* be optimistic */ t->_IsPowerOfTwo = GL_TRUE; /* may be set FALSE below */ /* Always need the base level image */ if (!t->Image[baseLevel]) { char s[100]; sprintf(s, "obj %p (%d) Image[baseLevel=%d] == NULL", (void *) t, t->Name, baseLevel); incomplete(t, s); t->Complete = GL_FALSE; return; } /* Check width/height/depth for zero */ if (t->Image[baseLevel]->Width == 0 || t->Image[baseLevel]->Height == 0 || t->Image[baseLevel]->Depth == 0) { incomplete(t, "texture width = 0"); t->Complete = GL_FALSE; return; } /* Compute _MaxLevel */ if (t->Target == GL_TEXTURE_1D) { maxLog2 = t->Image[baseLevel]->WidthLog2; maxLevels = ctx->Const.MaxTextureLevels; } else if (t->Target == GL_TEXTURE_2D) { maxLog2 = MAX2(t->Image[baseLevel]->WidthLog2, t->Image[baseLevel]->HeightLog2); maxLevels = ctx->Const.MaxTextureLevels; } else if (t->Target == GL_TEXTURE_3D) { GLint max = MAX2(t->Image[baseLevel]->WidthLog2, t->Image[baseLevel]->HeightLog2); maxLog2 = MAX2(max, (GLint)(t->Image[baseLevel]->DepthLog2)); maxLevels = ctx->Const.Max3DTextureLevels; } else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) { maxLog2 = MAX2(t->Image[baseLevel]->WidthLog2, t->Image[baseLevel]->HeightLog2); maxLevels = ctx->Const.MaxCubeTextureLevels; } else if (t->Target == GL_TEXTURE_RECTANGLE_NV) { maxLog2 = 0; /* not applicable */ maxLevels = 1; /* no mipmapping */ } else { _mesa_problem(ctx, "Bad t->Target in _mesa_test_texobj_completeness"); return; } ASSERT(maxLevels > 0); t->_MaxLevel = baseLevel + maxLog2; t->_MaxLevel = MIN2(t->_MaxLevel, t->MaxLevel); t->_MaxLevel = MIN2(t->_MaxLevel, maxLevels - 1); /* Compute _MaxLambda = q - b (see the 1.2 spec) used during mipmapping */ t->_MaxLambda = (GLfloat) (t->_MaxLevel - t->BaseLevel); if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) { /* make sure that all six cube map level 0 images are the same size */ const GLuint w = t->Image[baseLevel]->Width2; const GLuint h = t->Image[baseLevel]->Height2; if (!t->NegX[baseLevel] || t->NegX[baseLevel]->Width2 != w || t->NegX[baseLevel]->Height2 != h || !t->PosY[baseLevel] || t->PosY[baseLevel]->Width2 != w || t->PosY[baseLevel]->Height2 != h || !t->NegY[baseLevel] || t->NegY[baseLevel]->Width2 != w || t->NegY[baseLevel]->Height2 != h || !t->PosZ[baseLevel] || t->PosZ[baseLevel]->Width2 != w || t->PosZ[baseLevel]->Height2 != h || !t->NegZ[baseLevel] || t->NegZ[baseLevel]->Width2 != w || t->NegZ[baseLevel]->Height2 != h) { t->Complete = GL_FALSE; incomplete(t, "Non-quare cubemap image"); return; } } /* check for non power of two */ if (!t->Image[baseLevel]->_IsPowerOfTwo) { t->_IsPowerOfTwo = GL_FALSE; } /* extra checking for mipmaps */ if (t->MinFilter != GL_NEAREST && t->MinFilter != GL_LINEAR) { /* * Mipmapping: determine if we have a complete set of mipmaps */ GLint i; GLint minLevel = baseLevel; GLint maxLevel = t->_MaxLevel; if (minLevel > maxLevel) { t->Complete = GL_FALSE; incomplete(t, "minLevel > maxLevel"); return; } /* Test dimension-independent attributes */ for (i = minLevel; i <= maxLevel; i++) { if (t->Image[i]) { if (t->Image[i]->TexFormat != t->Image[baseLevel]->TexFormat) { t->Complete = GL_FALSE; incomplete(t, "Format[i] != Format[baseLevel]"); return; } if (t->Image[i]->Border != t->Image[baseLevel]->Border) { t->Complete = GL_FALSE; incomplete(t, "Border[i] != Border[baseLevel]"); return; } } } /* Test things which depend on number of texture image dimensions */ if (t->Target == GL_TEXTURE_1D) { /* Test 1-D mipmaps */ GLuint width = t->Image[baseLevel]->Width2; for (i = baseLevel + 1; i < maxLevels; i++) { if (width > 1) { width /= 2; } if (i >= minLevel && i <= maxLevel) { if (!t->Image[i]) { t->Complete = GL_FALSE; incomplete(t, "1D Image[i] == NULL"); return; } if (t->Image[i]->Width2 != width ) { t->Complete = GL_FALSE; incomplete(t, "1D Image[i] bad width"); return; } } if (width == 1) { return; /* found smallest needed mipmap, all done! */ } } } else if (t->Target == GL_TEXTURE_2D) { /* Test 2-D mipmaps */ GLuint width = t->Image[baseLevel]->Width2; GLuint height = t->Image[baseLevel]->Height2; for (i = baseLevel + 1; i < maxLevels; i++) { if (width > 1) { width /= 2; } if (height > 1) { height /= 2; } if (i >= minLevel && i <= maxLevel) { if (!t->Image[i]) { t->Complete = GL_FALSE; incomplete(t, "2D Image[i] == NULL"); return; } if (t->Image[i]->Width2 != width) { t->Complete = GL_FALSE; incomplete(t, "2D Image[i] bad width"); return; } if (t->Image[i]->Height2 != height) { t->Complete = GL_FALSE; incomplete(t, "2D Image[i] bad height"); return; } if (width==1 && height==1) { return; /* found smallest needed mipmap, all done! */ } } } } else if (t->Target == GL_TEXTURE_3D) { /* Test 3-D mipmaps */ GLuint width = t->Image[baseLevel]->Width2; GLuint height = t->Image[baseLevel]->Height2; GLuint depth = t->Image[baseLevel]->Depth2; for (i = baseLevel + 1; i < maxLevels; i++) { if (width > 1) { width /= 2; } if (height > 1) { height /= 2; } if (depth > 1) { depth /= 2; } if (i >= minLevel && i <= maxLevel) { if (!t->Image[i]) { incomplete(t, "3D Image[i] == NULL"); t->Complete = GL_FALSE; return; } if (t->Image[i]->Format == GL_DEPTH_COMPONENT) { t->Complete = GL_FALSE; incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex"); return; } if (t->Image[i]->Width2 != width) { t->Complete = GL_FALSE; incomplete(t, "3D Image[i] bad width"); return; } if (t->Image[i]->Height2 != height) { t->Complete = GL_FALSE; incomplete(t, "3D Image[i] bad height"); return; } if (t->Image[i]->Depth2 != depth) { t->Complete = GL_FALSE; incomplete(t, "3D Image[i] bad depth"); return; } } if (width == 1 && height == 1 && depth == 1) { return; /* found smallest needed mipmap, all done! */ } } } else if (t->Target == GL_TEXTURE_CUBE_MAP_ARB) { /* make sure 6 cube faces are consistant */ GLuint width = t->Image[baseLevel]->Width2; GLuint height = t->Image[baseLevel]->Height2; for (i = baseLevel + 1; i < maxLevels; i++) { if (width > 1) { width /= 2; } if (height > 1) { height /= 2; } if (i >= minLevel && i <= maxLevel) { /* check that we have images defined */ if (!t->Image[i] || !t->NegX[i] || !t->PosY[i] || !t->NegY[i] || !t->PosZ[i] || !t->NegZ[i]) { t->Complete = GL_FALSE; incomplete(t, "CubeMap Image[i] == NULL"); return; } /* Don't support GL_DEPTH_COMPONENT for cube maps */ if (t->Image[i]->Format == GL_DEPTH_COMPONENT) { t->Complete = GL_FALSE; incomplete(t, "GL_DEPTH_COMPONENT only works with 1/2D tex"); return; } /* check that all six images have same size */ if (t->NegX[i]->Width2!=width || t->NegX[i]->Height2!=height || t->PosY[i]->Width2!=width || t->PosY[i]->Height2!=height || t->NegY[i]->Width2!=width || t->NegY[i]->Height2!=height || t->PosZ[i]->Width2!=width || t->PosZ[i]->Height2!=height || t->NegZ[i]->Width2!=width || t->NegZ[i]->Height2!=height) { t->Complete = GL_FALSE; incomplete(t, "CubeMap Image[i] bad size"); return; } } if (width == 1 && height == 1) { return; /* found smallest needed mipmap, all done! */ } } } else if (t->Target == GL_TEXTURE_RECTANGLE_NV) { /* XXX special checking? */ } else { /* Target = ??? */ _mesa_problem(ctx, "Bug in gl_test_texture_object_completeness\n"); } } }
static PyObject *M_Geometry_LineIntersect2D( PyObject * self, PyObject * args ) { VectorObject *line_a1, *line_a2, *line_b1, *line_b2; float a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y, xi, yi, a1,a2,b1,b2, newvec[2]; if( !PyArg_ParseTuple ( args, "O!O!O!O!", &vector_Type, &line_a1, &vector_Type, &line_a2, &vector_Type, &line_b1, &vector_Type, &line_b2) ) { PyErr_SetString( PyExc_TypeError, "expected 4 vector types\n" ); return NULL; } if(!BaseMath_ReadCallback(line_a1) || !BaseMath_ReadCallback(line_a2) || !BaseMath_ReadCallback(line_b1) || !BaseMath_ReadCallback(line_b2)) return NULL; a1x= line_a1->vec[0]; a1y= line_a1->vec[1]; a2x= line_a2->vec[0]; a2y= line_a2->vec[1]; b1x= line_b1->vec[0]; b1y= line_b1->vec[1]; b2x= line_b2->vec[0]; b2y= line_b2->vec[1]; if((MIN2(a1x, a2x) > MAX2(b1x, b2x)) || (MAX2(a1x, a2x) < MIN2(b1x, b2x)) || (MIN2(a1y, a2y) > MAX2(b1y, b2y)) || (MAX2(a1y, a2y) < MIN2(b1y, b2y)) ) { Py_RETURN_NONE; } /* Make sure the hoz/vert line comes first. */ if (fabs(b1x - b2x) < eul || fabs(b1y - b2y) < eul) { SWAP_FLOAT(a1x, b1x, xi); /*abuse xi*/ SWAP_FLOAT(a1y, b1y, xi); SWAP_FLOAT(a2x, b2x, xi); SWAP_FLOAT(a2y, b2y, xi); } if (fabs(a1x-a2x) < eul) { /* verticle line */ if (fabs(b1x-b2x) < eul){ /*verticle second line */ Py_RETURN_NONE; /* 2 verticle lines dont intersect. */ } else if (fabs(b1y-b2y) < eul) { /*X of vert, Y of hoz. no calculation needed */ newvec[0]= a1x; newvec[1]= b1y; return newVectorObject(newvec, 2, Py_NEW, NULL); } yi = (float)(((b1y / fabs(b1x - b2x)) * fabs(b2x - a1x)) + ((b2y / fabs(b1x - b2x)) * fabs(b1x - a1x))); if (yi > MAX2(a1y, a2y)) {/* New point above seg1's vert line */ Py_RETURN_NONE; } else if (yi < MIN2(a1y, a2y)) { /* New point below seg1's vert line */ Py_RETURN_NONE; } newvec[0]= a1x; newvec[1]= yi; return newVectorObject(newvec, 2, Py_NEW, NULL); } else if (fabs(a2y-a1y) < eul) { /* hoz line1 */ if (fabs(b2y-b1y) < eul) { /*hoz line2*/ Py_RETURN_NONE; /*2 hoz lines dont intersect*/ } /* Can skip vert line check for seg 2 since its covered above. */ xi = (float)(((b1x / fabs(b1y - b2y)) * fabs(b2y - a1y)) + ((b2x / fabs(b1y - b2y)) * fabs(b1y - a1y))); if (xi > MAX2(a1x, a2x)) { /* New point right of hoz line1's */ Py_RETURN_NONE; } else if (xi < MIN2(a1x, a2x)) { /*New point left of seg1's hoz line */ Py_RETURN_NONE; } newvec[0]= xi; newvec[1]= a1y; return newVectorObject(newvec, 2, Py_NEW, NULL); } b1 = (a2y-a1y)/(a2x-a1x); b2 = (b2y-b1y)/(b2x-b1x); a1 = a1y-b1*a1x; a2 = b1y-b2*b1x; if (b1 - b2 == 0.0) { Py_RETURN_NONE; } xi = - (a1-a2)/(b1-b2); yi = a1+b1*xi; if ((a1x-xi)*(xi-a2x) >= 0 && (b1x-xi)*(xi-b2x) >= 0 && (a1y-yi)*(yi-a2y) >= 0 && (b1y-yi)*(yi-b2y)>=0) { newvec[0]= xi; newvec[1]= yi; return newVectorObject(newvec, 2, Py_NEW, NULL); } Py_RETURN_NONE; }
static void si_blit_decompress_depth(struct pipe_context *ctx, struct r600_texture *texture, struct r600_texture *staging, unsigned first_level, unsigned last_level, unsigned first_layer, unsigned last_layer, unsigned first_sample, unsigned last_sample) { struct si_context *sctx = (struct si_context *)ctx; unsigned layer, level, sample, checked_last_layer, max_layer; float depth = 1.0f; const struct util_format_description *desc; assert(staging != NULL && "use si_blit_decompress_zs_in_place instead"); desc = util_format_description(staging->resource.b.b.format); if (util_format_has_depth(desc)) sctx->dbcb_depth_copy_enabled = true; if (util_format_has_stencil(desc)) sctx->dbcb_stencil_copy_enabled = true; assert(sctx->dbcb_depth_copy_enabled || sctx->dbcb_stencil_copy_enabled); for (level = first_level; level <= last_level; level++) { /* The smaller the mipmap level, the less layers there are * as far as 3D textures are concerned. */ max_layer = util_max_layer(&texture->resource.b.b, level); checked_last_layer = MIN2(last_layer, max_layer); for (layer = first_layer; layer <= checked_last_layer; layer++) { for (sample = first_sample; sample <= last_sample; sample++) { struct pipe_surface *zsurf, *cbsurf, surf_tmpl; sctx->dbcb_copy_sample = sample; si_mark_atom_dirty(sctx, &sctx->db_render_state); surf_tmpl.format = texture->resource.b.b.format; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = layer; surf_tmpl.u.tex.last_layer = layer; zsurf = ctx->create_surface(ctx, &texture->resource.b.b, &surf_tmpl); surf_tmpl.format = staging->resource.b.b.format; cbsurf = ctx->create_surface(ctx, (struct pipe_resource*)staging, &surf_tmpl); si_blitter_begin(ctx, SI_DECOMPRESS); util_blitter_custom_depth_stencil(sctx->blitter, zsurf, cbsurf, 1 << sample, sctx->custom_dsa_flush, depth); si_blitter_end(ctx); pipe_surface_reference(&zsurf, NULL); pipe_surface_reference(&cbsurf, NULL); } } } sctx->dbcb_depth_copy_enabled = false; sctx->dbcb_stencil_copy_enabled = false; si_mark_atom_dirty(sctx, &sctx->db_render_state); }
/** * Copy pixel block from src surface to dst surface. * Overlapping regions are acceptable. * Flipping and stretching are supported. * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR * \param writemask controls which channels in the dest surface are sourced * from the src surface. Disabled channels are sourced * from (0,0,0,1). */ void util_blit_pixels(struct blit_state *ctx, struct pipe_resource *src_tex, unsigned src_level, int srcX0, int srcY0, int srcX1, int srcY1, int srcZ0, struct pipe_surface *dst, int dstX0, int dstY0, int dstX1, int dstY1, float z, uint filter, uint writemask, uint zs_writemask) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; enum pipe_format src_format, dst_format; struct pipe_sampler_view *sampler_view = NULL; struct pipe_sampler_view sv_templ; struct pipe_surface *dst_surface; struct pipe_framebuffer_state fb; const int srcW = abs(srcX1 - srcX0); const int srcH = abs(srcY1 - srcY0); unsigned offset; boolean overlap; float s0, t0, s1, t1; boolean normalized; boolean is_stencil, is_depth, blit_depth, blit_stencil; const struct util_format_description *src_desc = util_format_description(src_tex->format); assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); assert(src_level <= src_tex->last_level); /* do the regions overlap? */ overlap = src_tex == dst->texture && dst->u.tex.level == src_level && dst->u.tex.first_layer == srcZ0 && regions_overlap(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1); src_format = util_format_linear(src_tex->format); dst_format = util_format_linear(dst->texture->format); /* See whether we will blit depth or stencil. */ is_depth = util_format_has_depth(src_desc); is_stencil = util_format_has_stencil(src_desc); blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z); blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL); assert((writemask && !zs_writemask && !is_depth && !is_stencil) || (!writemask && (blit_depth || blit_stencil))); /* * Check for simple case: no format conversion, no flipping, no stretching, * no overlapping, same number of samples. * Filter mode should not matter since there's no stretching. */ if (formats_compatible(src_format, dst_format) && src_tex->nr_samples == dst->texture->nr_samples && is_stencil == blit_stencil && is_depth == blit_depth && srcX0 < srcX1 && dstX0 < dstX1 && srcY0 < srcY1 && dstY0 < dstY1 && (dstX1 - dstX0) == (srcX1 - srcX0) && (dstY1 - dstY0) == (srcY1 - srcY0) && !overlap) { struct pipe_box src_box; src_box.x = srcX0; src_box.y = srcY0; src_box.z = srcZ0; src_box.width = srcW; src_box.height = srcH; src_box.depth = 1; pipe->resource_copy_region(pipe, dst->texture, dst->u.tex.level, dstX0, dstY0, dst->u.tex.first_layer,/* dest */ src_tex, src_level, &src_box); return; } /* XXX Reading multisample textures is unimplemented. */ assert(src_tex->nr_samples <= 1); if (src_tex->nr_samples > 1) { return; } /* It's a mistake to call this function with a stencil format and * without shader stencil export. We don't do software fallbacks here. * Ignore stencil and only copy depth. */ if (blit_stencil && !ctx->has_stencil_export) { blit_stencil = FALSE; if (!blit_depth) return; } if (dst_format == dst->format) { dst_surface = dst; } else { struct pipe_surface templ = *dst; templ.format = dst_format; dst_surface = pipe->create_surface(pipe, dst->texture, &templ); } /* Create a temporary texture when src and dest alias. */ if (src_tex == dst_surface->texture && dst_surface->u.tex.level == src_level && dst_surface->u.tex.first_layer == srcZ0) { /* Make a temporary texture which contains a copy of the source pixels. * Then we'll sample from the temporary texture. */ struct pipe_resource texTemp; struct pipe_resource *tex; struct pipe_sampler_view sv_templ; struct pipe_box src_box; const int srcLeft = MIN2(srcX0, srcX1); const int srcTop = MIN2(srcY0, srcY1); if (srcLeft != srcX0) { /* left-right flip */ int tmp = dstX0; dstX0 = dstX1; dstX1 = tmp; } if (srcTop != srcY0) { /* up-down flip */ int tmp = dstY0; dstY0 = dstY1; dstY1 = tmp; } /* create temp texture */ memset(&texTemp, 0, sizeof(texTemp)); texTemp.target = ctx->internal_target; texTemp.format = src_format; texTemp.last_level = 0; texTemp.width0 = srcW; texTemp.height0 = srcH; texTemp.depth0 = 1; texTemp.array_size = 1; texTemp.bind = PIPE_BIND_SAMPLER_VIEW; tex = screen->resource_create(screen, &texTemp); if (!tex) return; src_box.x = srcLeft; src_box.y = srcTop; src_box.z = srcZ0; src_box.width = srcW; src_box.height = srcH; src_box.depth = 1; /* load temp texture */ pipe->resource_copy_region(pipe, tex, 0, 0, 0, 0, /* dest */ src_tex, src_level, &src_box); normalized = tex->target != PIPE_TEXTURE_RECT; if(normalized) { s0 = 0.0f; s1 = 1.0f; t0 = 0.0f; t1 = 1.0f; } else { s0 = 0; s1 = srcW; t0 = 0; t1 = srcH; } u_sampler_view_default_template(&sv_templ, tex, tex->format); if (!blit_depth && blit_stencil) { /* set a stencil-only format, e.g. Z24S8 --> X24S8 */ sv_templ.format = util_format_stencil_only(tex->format); assert(sv_templ.format != PIPE_FORMAT_NONE); } sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ); if (!sampler_view) { pipe_resource_reference(&tex, NULL); return; } pipe_resource_reference(&tex, NULL); } else { /* Directly sample from the source resource/texture */ u_sampler_view_default_template(&sv_templ, src_tex, src_format); if (!blit_depth && blit_stencil) { /* set a stencil-only format, e.g. Z24S8 --> X24S8 */ sv_templ.format = util_format_stencil_only(src_format); assert(sv_templ.format != PIPE_FORMAT_NONE); } sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ); if (!sampler_view) { return; } s0 = srcX0; s1 = srcX1; t0 = srcY0; t1 = srcY1; normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT; if(normalized) { s0 /= (float)(u_minify(sampler_view->texture->width0, src_level)); s1 /= (float)(u_minify(sampler_view->texture->width0, src_level)); t0 /= (float)(u_minify(sampler_view->texture->height0, src_level)); t1 /= (float)(u_minify(sampler_view->texture->height0, src_level)); } } assert(screen->is_format_supported(screen, sampler_view->format, ctx->internal_target, sampler_view->texture->nr_samples, PIPE_BIND_SAMPLER_VIEW)); assert(screen->is_format_supported(screen, dst_format, ctx->internal_target, dst_surface->texture->nr_samples, is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET)); /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_depth_stencil_alpha(ctx->cso); cso_save_rasterizer(ctx->cso); cso_save_sample_mask(ctx->cso); cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); cso_save_stream_outputs(ctx->cso); cso_save_viewport(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); cso_save_geometry_shader(ctx->cso); cso_save_vertex_elements(ctx->cso); cso_save_aux_vertex_buffer_slot(ctx->cso); cso_save_render_condition(ctx->cso); /* set misc state we care about */ if (writemask) cso_set_blend(ctx->cso, &ctx->blend_write_color); else cso_set_blend(ctx->cso, &ctx->blend_keep_color); cso_set_sample_mask(ctx->cso, ~0); cso_set_rasterizer(ctx->cso, &ctx->rasterizer); cso_set_vertex_elements(ctx->cso, 2, ctx->velem); cso_set_stream_outputs(ctx->cso, 0, NULL, 0); cso_set_render_condition(ctx->cso, NULL, 0); /* default sampler state */ ctx->sampler.normalized_coords = normalized; ctx->sampler.min_img_filter = filter; ctx->sampler.mag_img_filter = filter; ctx->sampler.min_lod = src_level; ctx->sampler.max_lod = src_level; /* Depth stencil state, fragment shader and sampler setup depending on what * we blit. */ if (blit_depth && blit_stencil) { cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); /* don't filter stencil */ ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &ctx->sampler); cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil); set_depthstencil_fragment_shader(ctx, sampler_view->texture->target); } else if (blit_depth) { cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth); set_depth_fragment_shader(ctx, sampler_view->texture->target); } else if (blit_stencil) { /* don't filter stencil */ ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil); set_stencil_fragment_shader(ctx, sampler_view->texture->target); } else { /* color */ cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler); cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil); set_fragment_shader(ctx, writemask, sampler_view->texture->target); } cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT); /* textures */ if (blit_depth && blit_stencil) { /* Setup two samplers, one for depth and the other one for stencil. */ struct pipe_sampler_view templ; struct pipe_sampler_view *views[2]; templ = *sampler_view; templ.format = util_format_stencil_only(templ.format); assert(templ.format != PIPE_FORMAT_NONE); views[0] = sampler_view; views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ); cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 2, views); pipe_sampler_view_reference(&views[1], NULL); } else { cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view); } /* viewport */ ctx->viewport.scale[0] = 0.5f * dst_surface->width; ctx->viewport.scale[1] = 0.5f * dst_surface->height; ctx->viewport.scale[2] = 0.5f; ctx->viewport.scale[3] = 1.0f; ctx->viewport.translate[0] = 0.5f * dst_surface->width; ctx->viewport.translate[1] = 0.5f * dst_surface->height; ctx->viewport.translate[2] = 0.5f; ctx->viewport.translate[3] = 0.0f; cso_set_viewport(ctx->cso, &ctx->viewport); set_vertex_shader(ctx); cso_set_geometry_shader_handle(ctx->cso, NULL); /* drawing dest */ memset(&fb, 0, sizeof(fb)); fb.width = dst_surface->width; fb.height = dst_surface->height; if (blit_depth || blit_stencil) { fb.zsbuf = dst_surface; } else { fb.nr_cbufs = 1; fb.cbufs[0] = dst_surface; } cso_set_framebuffer(ctx->cso, &fb); /* draw quad */ offset = setup_vertex_data_tex(ctx, (float) dstX0 / dst_surface->width * 2.0f - 1.0f, (float) dstY0 / dst_surface->height * 2.0f - 1.0f, (float) dstX1 / dst_surface->width * 2.0f - 1.0f, (float) dstY1 / dst_surface->height * 2.0f - 1.0f, s0, t0, s1, t1, z); if (ctx->vbuf) { util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf, cso_get_aux_vertex_buffer_slot(ctx->cso), offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ } /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_depth_stencil_alpha(ctx->cso); cso_restore_rasterizer(ctx->cso); cso_restore_sample_mask(ctx->cso); cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT); cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT); cso_restore_viewport(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_geometry_shader(ctx->cso); cso_restore_vertex_elements(ctx->cso); cso_restore_aux_vertex_buffer_slot(ctx->cso); cso_restore_stream_outputs(ctx->cso); cso_restore_render_condition(ctx->cso); pipe_sampler_view_reference(&sampler_view, NULL); if (dst_surface != dst) pipe_surface_reference(&dst_surface, NULL); }
// Similar to PSYoungGen::resize_generation() but // allows sum of eden_size and 2 * survivor_size to exceed _max_gen_size // expands at the low end of the virtual space // moves the boundary between the generations in order to expand // some additional diagnostics // If no additional changes are required, this can be deleted // and the changes factored back into PSYoungGen::resize_generation(). bool ASPSYoungGen::resize_generation(size_t eden_size, size_t survivor_size) { const size_t alignment = virtual_space()->alignment(); size_t orig_size = virtual_space()->committed_size(); bool size_changed = false; // There used to be a guarantee here that // (eden_size + 2*survivor_size) <= _max_gen_size // This requirement is enforced by the calculation of desired_size // below. It may not be true on entry since the size of the // eden_size is no bounded by the generation size. assert(max_size() == reserved().byte_size(), "max gen size problem?"); assert(min_gen_size() <= orig_size && orig_size <= max_size(), "just checking"); // Adjust new generation size const size_t eden_plus_survivors = align_size_up(eden_size + 2 * survivor_size, alignment); size_t desired_size = MAX2(MIN2(eden_plus_survivors, gen_size_limit()), min_gen_size()); assert(desired_size <= gen_size_limit(), "just checking"); if (desired_size > orig_size) { // Grow the generation size_t change = desired_size - orig_size; HeapWord* prev_low = (HeapWord*) virtual_space()->low(); if (!virtual_space()->expand_by(change)) { return false; } if (ZapUnusedHeapArea) { // Mangle newly committed space immediately because it // can be done here more simply that after the new // spaces have been computed. HeapWord* new_low = (HeapWord*) virtual_space()->low(); assert(new_low < prev_low, "Did not grow"); MemRegion mangle_region(new_low, prev_low); SpaceMangler::mangle_region(mangle_region); } size_changed = true; } else if (desired_size < orig_size) { size_t desired_change = orig_size - desired_size; // How much is available for shrinking. size_t available_bytes = limit_gen_shrink(desired_change); size_t change = MIN2(desired_change, available_bytes); virtual_space()->shrink_by(change); size_changed = true; } else { if (Verbose && PrintGC) { if (orig_size == gen_size_limit()) { gclog_or_tty->print_cr("ASPSYoung generation size at maximum: " SIZE_FORMAT "K", orig_size/K); } else if (orig_size == min_gen_size()) { gclog_or_tty->print_cr("ASPSYoung generation size at minium: " SIZE_FORMAT "K", orig_size/K); } } } if (size_changed) { reset_after_change(); if (Verbose && PrintGC) { size_t current_size = virtual_space()->committed_size(); gclog_or_tty->print_cr("ASPSYoung generation size changed: " SIZE_FORMAT "K->" SIZE_FORMAT "K", orig_size/K, current_size/K); } } guarantee(eden_plus_survivors <= virtual_space()->committed_size() || virtual_space()->committed_size() == max_size(), "Sanity"); return true; }