From: Chia-I Wu Date: Mon, 29 Nov 2010 03:49:18 +0000 (+0800) Subject: st/vega: Add color transformation support. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e360f91f152615b35857a4d008d0439a3c3285a8;p=mesa.git st/vega: Add color transformation support. Per OpenVG 1.1. A new shader stage is added. It uses the first two constants of the fragment shader for color transformation parameters. --- diff --git a/src/gallium/state_trackers/vega/asm_fill.h b/src/gallium/state_trackers/vega/asm_fill.h index 3f09e73f194..0e29aab88a6 100644 --- a/src/gallium/state_trackers/vega/asm_fill.h +++ b/src/gallium/state_trackers/vega/asm_fill.h @@ -44,7 +44,7 @@ solid_fill( struct ureg_program *ureg, struct ureg_dst *temp, struct ureg_src *constant) { - ureg_MOV(ureg, *out, constant[0]); + ureg_MOV(ureg, *out, constant[2]); } static INLINE void @@ -61,24 +61,24 @@ linear_grad( struct ureg_program *ureg, in[0]); ureg_MOV(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_Z), - ureg_scalar(constant[1], TGSI_SWIZZLE_Y)); - ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0])); - ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0])); - ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0])); + ureg_scalar(constant[3], TGSI_SWIZZLE_Y)); + ureg_DP3(ureg, temp[1], constant[4], ureg_src(temp[0])); + ureg_DP3(ureg, temp[2], constant[5], ureg_src(temp[0])); + ureg_DP3(ureg, temp[3], constant[6], ureg_src(temp[0])); ureg_RCP(ureg, temp[3], ureg_src(temp[3])); ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3])); ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3])); ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_X), ureg_src(temp[1])); ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_Y), ureg_src(temp[2])); ureg_MUL(ureg, temp[0], - ureg_scalar(constant[0], TGSI_SWIZZLE_Y), + ureg_scalar(constant[2], TGSI_SWIZZLE_Y), ureg_scalar(ureg_src(temp[4]), TGSI_SWIZZLE_Y)); ureg_MAD(ureg, temp[1], - ureg_scalar(constant[0], TGSI_SWIZZLE_X), + ureg_scalar(constant[2], TGSI_SWIZZLE_X), ureg_scalar(ureg_src(temp[4]), TGSI_SWIZZLE_X), ureg_src(temp[0])); ureg_MUL(ureg, temp[2], ureg_src(temp[1]), - ureg_scalar(constant[0], TGSI_SWIZZLE_Z)); + ureg_scalar(constant[2], TGSI_SWIZZLE_Z)); ureg_TEX(ureg, *out, TGSI_TEXTURE_1D, ureg_src(temp[2]), sampler[0]); } @@ -94,19 +94,19 @@ radial_grad( struct ureg_program *ureg, ureg_MOV(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_XY), in[0]); ureg_MOV(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_Z), - ureg_scalar(constant[1], TGSI_SWIZZLE_Y)); - ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0])); - ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0])); - ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0])); + ureg_scalar(constant[3], TGSI_SWIZZLE_Y)); + ureg_DP3(ureg, temp[1], constant[4], ureg_src(temp[0])); + ureg_DP3(ureg, temp[2], constant[5], ureg_src(temp[0])); + ureg_DP3(ureg, temp[3], constant[6], ureg_src(temp[0])); ureg_RCP(ureg, temp[3], ureg_src(temp[3])); ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3])); ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3])); ureg_MOV(ureg, ureg_writemask(temp[5], TGSI_WRITEMASK_X), ureg_src(temp[1])); ureg_MOV(ureg, ureg_writemask(temp[5], TGSI_WRITEMASK_Y), ureg_src(temp[2])); - ureg_MUL(ureg, temp[0], ureg_scalar(constant[0], TGSI_SWIZZLE_Y), + ureg_MUL(ureg, temp[0], ureg_scalar(constant[2], TGSI_SWIZZLE_Y), ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_Y)); ureg_MAD(ureg, temp[1], - ureg_scalar(constant[0], TGSI_SWIZZLE_X), + ureg_scalar(constant[2], TGSI_SWIZZLE_X), ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_X), ureg_src(temp[0])); ureg_ADD(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[1])); ureg_MUL(ureg, temp[3], @@ -118,10 +118,10 @@ radial_grad( struct ureg_program *ureg, ureg_src(temp[3])); ureg_MOV(ureg, temp[4], ureg_negate(ureg_src(temp[4]))); ureg_MUL(ureg, temp[2], - ureg_scalar(constant[0], TGSI_SWIZZLE_Z), + ureg_scalar(constant[2], TGSI_SWIZZLE_Z), ureg_src(temp[4])); ureg_MUL(ureg, temp[0], - ureg_scalar(constant[1], TGSI_SWIZZLE_W), + ureg_scalar(constant[3], TGSI_SWIZZLE_W), ureg_src(temp[2])); ureg_MUL(ureg, temp[3], ureg_src(temp[1]), ureg_src(temp[1])); @@ -130,8 +130,8 @@ radial_grad( struct ureg_program *ureg, ureg_RCP(ureg, temp[2], ureg_src(temp[2])); ureg_SUB(ureg, temp[1], ureg_src(temp[2]), ureg_src(temp[1])); ureg_ADD(ureg, temp[0], - ureg_scalar(constant[0], TGSI_SWIZZLE_Z), - ureg_scalar(constant[0], TGSI_SWIZZLE_Z)); + ureg_scalar(constant[2], TGSI_SWIZZLE_Z), + ureg_scalar(constant[2], TGSI_SWIZZLE_Z)); ureg_RCP(ureg, temp[0], ureg_src(temp[0])); ureg_MUL(ureg, temp[2], ureg_src(temp[1]), ureg_src(temp[0])); ureg_TEX(ureg, *out, TGSI_TEXTURE_1D, ureg_src(temp[2]), sampler[0]); @@ -152,17 +152,17 @@ pattern( struct ureg_program *ureg, in[0]); ureg_MOV(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_Z), - ureg_scalar(constant[1], TGSI_SWIZZLE_Y)); - ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0])); - ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0])); - ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0])); + ureg_scalar(constant[3], TGSI_SWIZZLE_Y)); + ureg_DP3(ureg, temp[1], constant[4], ureg_src(temp[0])); + ureg_DP3(ureg, temp[2], constant[5], ureg_src(temp[0])); + ureg_DP3(ureg, temp[3], constant[6], ureg_src(temp[0])); ureg_RCP(ureg, temp[3], ureg_src(temp[3])); ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3])); ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3])); ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_X), ureg_src(temp[1])); ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_Y), ureg_src(temp[2])); ureg_RCP(ureg, temp[0], - ureg_swizzle(constant[1], + ureg_swizzle(constant[3], TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W, TGSI_SWIZZLE_Z, @@ -179,6 +179,23 @@ pattern( struct ureg_program *ureg, ureg_TEX(ureg, *out, TGSI_TEXTURE_2D, ureg_src(temp[1]), sampler[0]); } +static INLINE void +color_transform( struct ureg_program *ureg, + struct ureg_dst *out, + struct ureg_src *in, + struct ureg_src *sampler, + struct ureg_dst *temp, + struct ureg_src *constant) +{ + ureg_MUL(ureg, temp[1], ureg_src(temp[0]), constant[0]); + ureg_ADD(ureg, temp[1], ureg_src(temp[1]), constant[1]); + ureg_CLAMP(ureg, temp[1], + ureg_src(temp[1]), + ureg_scalar(constant[3], TGSI_SWIZZLE_X), + ureg_scalar(constant[3], TGSI_SWIZZLE_Y)); + ureg_MOV(ureg, *out, ureg_src(temp[1])); +} + static INLINE void mask( struct ureg_program *ureg, struct ureg_dst *out, @@ -233,10 +250,10 @@ image_stencil( struct ureg_program *ureg, #define EXTENDED_BLENDER_OVER_FUNC \ ureg_SUB(ureg, temp[3], \ - ureg_scalar(constant[1], TGSI_SWIZZLE_Y), \ + ureg_scalar(constant[3], TGSI_SWIZZLE_Y), \ ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W)); \ ureg_SUB(ureg, temp[4], \ - ureg_scalar(constant[1], TGSI_SWIZZLE_Y), \ + ureg_scalar(constant[3], TGSI_SWIZZLE_Y), \ ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W)); \ ureg_MUL(ureg, temp[3], ureg_src(temp[0]), ureg_src(temp[3])); \ ureg_MUL(ureg, temp[4], ureg_src(temp[1]), ureg_src(temp[4])); \ @@ -369,11 +386,11 @@ color_bw( struct ureg_program *ureg, struct ureg_src *constant) { ureg_ADD(ureg, temp[1], - ureg_scalar(constant[1], TGSI_SWIZZLE_Y), - ureg_scalar(constant[1], TGSI_SWIZZLE_Y)); + ureg_scalar(constant[3], TGSI_SWIZZLE_Y), + ureg_scalar(constant[3], TGSI_SWIZZLE_Y)); ureg_RCP(ureg, temp[2], ureg_src(temp[1])); ureg_ADD(ureg, temp[1], - ureg_scalar(constant[1], TGSI_SWIZZLE_Y), + ureg_scalar(constant[3], TGSI_SWIZZLE_Y), ureg_src(temp[2])); ureg_ADD(ureg, ureg_writemask(temp[2], TGSI_WRITEMASK_X), ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_X), @@ -413,13 +430,13 @@ struct shader_asm_info { /* paint types */ static const struct shader_asm_info shaders_paint_asm[] = { {VEGA_SOLID_FILL_SHADER, solid_fill, - VG_FALSE, 0, 1, 0, 0, 0, 0}, + VG_FALSE, 2, 1, 0, 0, 0, 0}, {VEGA_LINEAR_GRADIENT_SHADER, linear_grad, - VG_TRUE, 0, 5, 0, 1, 0, 5}, + VG_TRUE, 2, 5, 0, 1, 0, 5}, {VEGA_RADIAL_GRADIENT_SHADER, radial_grad, - VG_TRUE, 0, 5, 0, 1, 0, 6}, + VG_TRUE, 2, 5, 0, 1, 0, 6}, {VEGA_PATTERN_SHADER, pattern, - VG_TRUE, 1, 4, 0, 1, 0, 5} + VG_TRUE, 3, 4, 0, 1, 0, 5} }; /* image draw modes */ @@ -432,6 +449,11 @@ static const struct shader_asm_info shaders_image_asm[] = { VG_TRUE, 0, 0, 3, 1, 0, 2} }; +static const struct shader_asm_info shaders_color_transform_asm[] = { + {VEGA_COLOR_TRANSFORM_SHADER, color_transform, + VG_FALSE, 0, 4, 0, 0, 0, 2} +}; + static const struct shader_asm_info shaders_mask_asm[] = { {VEGA_MASK_SHADER, mask, VG_TRUE, 0, 0, 1, 1, 0, 2} @@ -440,13 +462,13 @@ static const struct shader_asm_info shaders_mask_asm[] = { /* extra blend modes */ static const struct shader_asm_info shaders_blend_asm[] = { {VEGA_BLEND_MULTIPLY_SHADER, blend_multiply, - VG_TRUE, 1, 1, 2, 1, 0, 5}, + VG_TRUE, 3, 1, 2, 1, 0, 5}, {VEGA_BLEND_SCREEN_SHADER, blend_screen, VG_TRUE, 0, 0, 2, 1, 0, 4}, {VEGA_BLEND_DARKEN_SHADER, blend_darken, - VG_TRUE, 1, 1, 2, 1, 0, 6}, + VG_TRUE, 3, 1, 2, 1, 0, 6}, {VEGA_BLEND_LIGHTEN_SHADER, blend_lighten, - VG_TRUE, 1, 1, 2, 1, 0, 6}, + VG_TRUE, 3, 1, 2, 1, 0, 6}, }; /* premultiply */ @@ -460,7 +482,7 @@ static const struct shader_asm_info shaders_premultiply_asm[] = { /* color transform to black and white */ static const struct shader_asm_info shaders_bw_asm[] = { {VEGA_BW_SHADER, color_bw, - VG_FALSE, 1, 1, 0, 0, 0, 3}, + VG_FALSE, 3, 1, 0, 0, 0, 3}, }; #endif diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c index 0e25833cda3..670790c0238 100644 --- a/src/gallium/state_trackers/vega/mask.c +++ b/src/gallium/state_trackers/vega/mask.c @@ -253,7 +253,11 @@ static void mask_resource_fill(struct pipe_resource *dst, VGfloat coverage) { struct vg_context *ctx = vg_current_context(); - VGfloat color[4] = { 0.0f, 0.0f, 0.0f, coverage }; + VGfloat fs_consts[12] = { + 0.0f, 0.0f, 0.0f, 0.0f, /* not used */ + 0.0f, 0.0f, 0.0f, 0.0f, /* not used */ + 0.0f, 0.0f, 0.0f, coverage /* color */ + }; void *fs; if (x < 0) { @@ -267,8 +271,8 @@ static void mask_resource_fill(struct pipe_resource *dst, fs = shaders_cache_fill(ctx->sc, VEGA_SOLID_FILL_SHADER); - if (renderer_filter_begin(ctx->renderer, dst, VG_FALSE, - ~0, NULL, NULL, 0, fs, (const void *) color, sizeof(color))) { + if (renderer_filter_begin(ctx->renderer, dst, VG_FALSE, ~0, + NULL, NULL, 0, fs, (const void *) fs_consts, sizeof(fs_consts))) { renderer_filter(ctx->renderer, x, y, width, height, 0, 0, 0, 0); renderer_filter_end(ctx->renderer); } diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c index 080b37c586e..39c4bb0dfd6 100644 --- a/src/gallium/state_trackers/vega/shader.c +++ b/src/gallium/state_trackers/vega/shader.c @@ -38,12 +38,14 @@ #include "pipe/p_state.h" #include "util/u_inlines.h" #include "util/u_memory.h" +#include "util/u_math.h" -#define MAX_CONSTANTS 20 +#define MAX_CONSTANTS 28 struct shader { struct vg_context *context; + VGboolean color_transform; VGboolean masking; struct vg_paint *paint; struct vg_image *image; @@ -72,6 +74,11 @@ void shader_destroy(struct shader *shader) FREE(shader); } +void shader_set_color_transform(struct shader *shader, VGboolean set) +{ + shader->color_transform = set; +} + void shader_set_masking(struct shader *shader, VGboolean set) { shader->masking = set; @@ -94,10 +101,25 @@ struct vg_paint * shader_paint(struct shader *shader) static VGint setup_constant_buffer(struct shader *shader) { + const struct vg_state *state = &shader->context->state.vg; VGint param_bytes = paint_constant_buffer_size(shader->paint); + VGint i; + param_bytes += sizeof(VGfloat) * 8; assert(param_bytes <= sizeof(shader->constants)); - paint_fill_constant_buffer(shader->paint, shader->constants); + + if (state->color_transform) { + for (i = 0; i < 8; i++) { + VGfloat val = (i < 4) ? 127.0f : 1.0f; + shader->constants[i] = + CLAMP(state->color_transform_values[i], -val, val); + } + } + else { + memset(shader->constants, 0, sizeof(VGfloat) * 8); + } + + paint_fill_constant_buffer(shader->paint, shader->constants + 8); return param_bytes; } @@ -227,6 +249,9 @@ static void setup_shader_program(struct shader *shader) } } + if (shader->color_transform) + shader_id |= VEGA_COLOR_TRANSFORM_SHADER; + if (shader->masking) shader_id |= VEGA_MASK_SHADER; diff --git a/src/gallium/state_trackers/vega/shader.h b/src/gallium/state_trackers/vega/shader.h index 847eee6a310..f906631b50e 100644 --- a/src/gallium/state_trackers/vega/shader.h +++ b/src/gallium/state_trackers/vega/shader.h @@ -37,6 +37,8 @@ struct vg_image; struct shader *shader_create(struct vg_context *context); void shader_destroy(struct shader *shader); +void shader_set_color_transform(struct shader *shader, VGboolean set); + void shader_set_masking(struct shader *shader, VGboolean set); VGboolean shader_is_masking(struct shader *shader); diff --git a/src/gallium/state_trackers/vega/shaders_cache.c b/src/gallium/state_trackers/vega/shaders_cache.c index 49b451c1179..732d57de9a0 100644 --- a/src/gallium/state_trackers/vega/shaders_cache.c +++ b/src/gallium/state_trackers/vega/shaders_cache.c @@ -52,12 +52,13 @@ * of the pipeline. The stages are: * 1) Paint generation (color/gradient/pattern) * 2) Image composition (normal/multiply/stencil) - * 3) Mask - * 4) Extended blend (multiply/screen/darken/lighten) - * 5) Premultiply/Unpremultiply - * 6) Color transform (to black and white) + * 3) Color transform + * 4) Mask + * 5) Extended blend (multiply/screen/darken/lighten) + * 6) Premultiply/Unpremultiply + * 7) Color transform (to black and white) */ -#define SHADER_STAGES 6 +#define SHADER_STAGES 7 struct cached_shader { void *driver_shader; @@ -286,6 +287,19 @@ create_shader(struct pipe_context *pipe, assert(idx == ((!sh || sh == VEGA_IMAGE_NORMAL_SHADER) ? 1 : 2)); /* third stage */ + sh = SHADERS_GET_COLOR_TRANSFORM_SHADER(id); + switch (sh) { + case VEGA_COLOR_TRANSFORM_SHADER: + shaders[idx] = &shaders_color_transform_asm[ + (sh >> SHADERS_COLOR_TRANSFORM_SHIFT) - 1]; + assert(shaders[idx]->id == sh); + idx++; + break; + default: + break; + } + + /* fourth stage */ sh = SHADERS_GET_MASK_SHADER(id); switch (sh) { case VEGA_MASK_SHADER: @@ -297,7 +311,7 @@ create_shader(struct pipe_context *pipe, break; } - /* fourth stage */ + /* fifth stage */ sh = SHADERS_GET_BLEND_SHADER(id); switch (sh) { case VEGA_BLEND_MULTIPLY_SHADER: @@ -312,7 +326,7 @@ create_shader(struct pipe_context *pipe, break; } - /* fifth stage */ + /* sixth stage */ sh = SHADERS_GET_PREMULTIPLY_SHADER(id); switch (sh) { case VEGA_PREMULTIPLY_SHADER: @@ -326,7 +340,7 @@ create_shader(struct pipe_context *pipe, break; } - /* sixth stage */ + /* seventh stage */ sh = SHADERS_GET_BW_SHADER(id); switch (sh) { case VEGA_BW_SHADER: diff --git a/src/gallium/state_trackers/vega/shaders_cache.h b/src/gallium/state_trackers/vega/shaders_cache.h index 2d0c2da30ec..9c5ede6a244 100644 --- a/src/gallium/state_trackers/vega/shaders_cache.h +++ b/src/gallium/state_trackers/vega/shaders_cache.h @@ -35,6 +35,7 @@ struct shaders_cache; #define _SHADERS_PAINT_BITS 3 #define _SHADERS_IMAGE_BITS 2 +#define _SHADERS_COLOR_TRANSFORM_BITS 1 #define _SHADERS_MASK_BITS 1 #define _SHADERS_BLEND_BITS 3 #define _SHADERS_PREMULTIPLY_BITS 2 @@ -42,7 +43,8 @@ struct shaders_cache; #define SHADERS_PAINT_SHIFT (0) #define SHADERS_IMAGE_SHIFT (SHADERS_PAINT_SHIFT + _SHADERS_PAINT_BITS) -#define SHADERS_MASK_SHIFT (SHADERS_IMAGE_SHIFT + _SHADERS_IMAGE_BITS) +#define SHADERS_COLOR_TRANSFORM_SHIFT (SHADERS_IMAGE_SHIFT + _SHADERS_IMAGE_BITS) +#define SHADERS_MASK_SHIFT (SHADERS_COLOR_TRANSFORM_SHIFT + _SHADERS_COLOR_TRANSFORM_BITS) #define SHADERS_BLEND_SHIFT (SHADERS_MASK_SHIFT + _SHADERS_MASK_BITS) #define SHADERS_PREMULTIPLY_SHIFT (SHADERS_BLEND_SHIFT + _SHADERS_BLEND_BITS) #define SHADERS_BW_SHIFT (SHADERS_PREMULTIPLY_SHIFT + _SHADERS_PREMULTIPLY_BITS) @@ -52,6 +54,7 @@ struct shaders_cache; #define SHADERS_GET_PAINT_SHADER(id) _SHADERS_GET_STAGE(PAINT, id) #define SHADERS_GET_IMAGE_SHADER(id) _SHADERS_GET_STAGE(IMAGE, id) +#define SHADERS_GET_COLOR_TRANSFORM_SHADER(id) _SHADERS_GET_STAGE(COLOR_TRANSFORM, id) #define SHADERS_GET_MASK_SHADER(id) _SHADERS_GET_STAGE(MASK, id) #define SHADERS_GET_BLEND_SHADER(id) _SHADERS_GET_STAGE(BLEND, id) #define SHADERS_GET_PREMULTIPLY_SHADER(id) _SHADERS_GET_STAGE(PREMULTIPLY, id) @@ -67,6 +70,8 @@ enum VegaShaderType { VEGA_IMAGE_MULTIPLY_SHADER = 2 << SHADERS_IMAGE_SHIFT, VEGA_IMAGE_STENCIL_SHADER = 3 << SHADERS_IMAGE_SHIFT, + VEGA_COLOR_TRANSFORM_SHADER = 1 << SHADERS_COLOR_TRANSFORM_SHIFT, + VEGA_MASK_SHADER = 1 << SHADERS_MASK_SHIFT, VEGA_BLEND_MULTIPLY_SHADER = 1 << SHADERS_BLEND_SHIFT, diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c index 19f4e71e0d9..4d088b965df 100644 --- a/src/gallium/state_trackers/vega/vg_context.c +++ b/src/gallium/state_trackers/vega/vg_context.c @@ -416,6 +416,7 @@ void vg_validate_state(struct vg_context *ctx) shader_set_masking(ctx->shader, ctx->state.vg.masking); shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode); + shader_set_color_transform(ctx->shader, ctx->state.vg.color_transform); } VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type)