diff options
author | Christian König <[email protected]> | 2010-12-05 17:57:52 +0100 |
---|---|---|
committer | Christian König <[email protected]> | 2010-12-05 17:57:52 +0100 |
commit | 57018734023b41ef84f5be560c12dce6ae5f1c58 (patch) | |
tree | fbb885a35c3786a898f4d5310d7f541c27f2e512 /src/gallium/auxiliary/vl | |
parent | 8e0c05960daa7a38ab7834e6a9e7e0a7a973ac2d (diff) |
[g3dvl] move vertex handling into vl_vb object
Diffstat (limited to 'src/gallium/auxiliary/vl')
-rw-r--r-- | src/gallium/auxiliary/vl/vl_idct.c | 19 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c | 133 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h | 17 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_vertex_buffers.c | 19 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_vertex_buffers.h | 23 |
5 files changed, 94 insertions, 117 deletions
diff --git a/src/gallium/auxiliary/vl/vl_idct.c b/src/gallium/auxiliary/vl/vl_idct.c index a5b2053065e..66bb140f02a 100644 --- a/src/gallium/auxiliary/vl/vl_idct.c +++ b/src/gallium/auxiliary/vl/vl_idct.c @@ -618,7 +618,7 @@ vl_idct_init(struct vl_idct *idct, struct pipe_context *pipe, struct pipe_resour return false; } - if(!vl_vb_init(&idct->blocks, idct->max_blocks)) { + if(!vl_vb_init(&idct->blocks, idct->max_blocks, 2)) { cleanup_shaders(idct); cleanup_buffers(idct); return false; @@ -646,6 +646,7 @@ vl_idct_cleanup(struct vl_idct *idct) void vl_idct_add_block(struct vl_idct *idct, unsigned x, unsigned y, short *block) { + struct vertex2f v; unsigned tex_pitch; short *texels; @@ -659,15 +660,17 @@ vl_idct_add_block(struct vl_idct *idct, unsigned x, unsigned y, short *block) for (i = 0; i < BLOCK_HEIGHT; ++i) memcpy(texels + i * tex_pitch, block + i * BLOCK_WIDTH, BLOCK_WIDTH * sizeof(short)); - vl_vb_add_block(&idct->blocks, x, y); + v.x = x; + v.y = y; + vl_vb_add_block(&idct->blocks, (float*)&v); } void vl_idct_flush(struct vl_idct *idct) { struct pipe_transfer *vec_transfer; - struct quadf *vectors; - unsigned num_blocks; + void *vectors; + unsigned num_verts; assert(idct); @@ -679,13 +682,13 @@ vl_idct_flush(struct vl_idct *idct) &vec_transfer ); - num_blocks = vl_vb_upload(&idct->blocks, vectors); + num_verts = vl_vb_upload(&idct->blocks, vectors); pipe_buffer_unmap(idct->pipe, idct->vertex_bufs.individual.pos.buffer, vec_transfer); xfer_buffers_unmap(idct); - if(num_blocks > 0) { + if(num_verts > 0) { idct->pipe->bind_rasterizer_state(idct->pipe, idct->rs_state); idct->pipe->set_vertex_buffers(idct->pipe, 2, idct->vertex_bufs.all); @@ -698,7 +701,7 @@ vl_idct_flush(struct vl_idct *idct) idct->pipe->set_fragment_sampler_views(idct->pipe, 2, idct->sampler_views.stage[0]); idct->pipe->bind_fragment_sampler_states(idct->pipe, 2, idct->samplers.stage[0]); idct->pipe->bind_fs_state(idct->pipe, idct->matrix_fs); - util_draw_arrays(idct->pipe, PIPE_PRIM_QUADS, 0, num_blocks * 4); + util_draw_arrays(idct->pipe, PIPE_PRIM_QUADS, 0, num_verts); /* second stage */ idct->pipe->set_framebuffer_state(idct->pipe, &idct->fb_state[1]); @@ -706,7 +709,7 @@ vl_idct_flush(struct vl_idct *idct) idct->pipe->set_fragment_sampler_views(idct->pipe, 2, idct->sampler_views.stage[1]); idct->pipe->bind_fragment_sampler_states(idct->pipe, 2, idct->samplers.stage[1]); idct->pipe->bind_fs_state(idct->pipe, idct->transpose_fs); - util_draw_arrays(idct->pipe, PIPE_PRIM_QUADS, 0, num_blocks * 4); + util_draw_arrays(idct->pipe, PIPE_PRIM_QUADS, 0, num_verts); } xfer_buffers_map(idct); diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c index 76db8c1b211..064e6c1a2d5 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c +++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c @@ -48,6 +48,17 @@ struct vertex_shader_consts struct vertex4f norm; }; +struct vertex_stream_0 +{ + struct vertex2f pos; + struct { + float y; + float cr; + float cb; + } eb[2][2]; + float interlaced; +}; + enum VS_INPUT { VS_I_RECT, @@ -462,16 +473,11 @@ init_mbtype_handler(struct vl_mpeg12_mc_renderer *r, enum VL_MACROBLOCK_TYPE typ if (handler->vertex_elems_state == NULL) return false; - if (!vl_vb_init(&handler->pos, r->macroblocks_per_batch)) - return false; - - handler->info = MALLOC(sizeof(struct vertex_stream_0) * r->macroblocks_per_batch * 4); - if (handler->info == NULL) + if (!vl_vb_init(&handler->pos, r->macroblocks_per_batch, sizeof(struct vertex_stream_0) / sizeof(float))) return false; for (i = 0; i < ref_frames * mv_per_frame; ++i) { - handler->mv[i] = MALLOC(sizeof(struct vertex2f) * r->macroblocks_per_batch * 4); - if (handler->mv[i] == NULL) + if (!vl_vb_init(&handler->mv[i], r->macroblocks_per_batch, sizeof(struct vertex2f) / sizeof(float))) return false; } @@ -496,10 +502,10 @@ cleanup_mbtype_handler(struct vl_mpeg12_mc_renderer *r, enum VL_MACROBLOCK_TYPE r->pipe->delete_fs_state(r->pipe, handler->fs); r->pipe->delete_vertex_elements_state(r->pipe, handler->vertex_elems_state); - FREE(handler->info); + vl_vb_cleanup(&handler->pos); for (i = 0; i < ref_frames * mv_per_frame; ++i) - FREE(handler->mv[i]); + vl_vb_cleanup(&handler->mv[i]); } @@ -656,22 +662,11 @@ init_buffers(struct vl_mpeg12_mc_renderer *r) r->vertex_bufs.individual.quad = vl_vb_upload_quads(r->pipe, r->macroblocks_per_batch); - r->vertex_bufs.individual.ycbcr.stride = sizeof(struct vertex2f); - r->vertex_bufs.individual.ycbcr.max_index = 4 * r->macroblocks_per_batch - 1; - r->vertex_bufs.individual.ycbcr.buffer_offset = 0; - /* XXX: Create with usage DYNAMIC or STREAM */ - r->vertex_bufs.individual.ycbcr.buffer = pipe_buffer_create - ( - r->pipe->screen, - PIPE_BIND_VERTEX_BUFFER, - sizeof(struct vertex2f) * 4 * r->macroblocks_per_batch - ); - - r->vertex_bufs.individual.info.stride = sizeof(struct vertex_stream_0); - r->vertex_bufs.individual.info.max_index = 4 * r->macroblocks_per_batch - 1; - r->vertex_bufs.individual.info.buffer_offset = 0; + r->vertex_bufs.individual.pos.stride = sizeof(struct vertex_stream_0); + r->vertex_bufs.individual.pos.max_index = 4 * r->macroblocks_per_batch - 1; + r->vertex_bufs.individual.pos.buffer_offset = 0; /* XXX: Create with usage DYNAMIC or STREAM */ - r->vertex_bufs.individual.info.buffer = pipe_buffer_create + r->vertex_bufs.individual.pos.buffer = pipe_buffer_create ( r->pipe->screen, PIPE_BIND_VERTEX_BUFFER, @@ -706,57 +701,57 @@ init_buffers(struct vl_mpeg12_mc_renderer *r) vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R32G32_FLOAT; /* y, cr, cb empty block element top left block */ - vertex_elems[VS_I_EB_0_0].src_offset = 0; + vertex_elems[VS_I_EB_0_0].src_offset = sizeof(float) * 2; vertex_elems[VS_I_EB_0_0].instance_divisor = 0; - vertex_elems[VS_I_EB_0_0].vertex_buffer_index = 2; + vertex_elems[VS_I_EB_0_0].vertex_buffer_index = 1; vertex_elems[VS_I_EB_0_0].src_format = PIPE_FORMAT_R32G32B32_FLOAT; /* y, cr, cb empty block element top right block */ - vertex_elems[VS_I_EB_0_1].src_offset = sizeof(float) * 3; + vertex_elems[VS_I_EB_0_1].src_offset = sizeof(float) * 5; vertex_elems[VS_I_EB_0_1].instance_divisor = 0; - vertex_elems[VS_I_EB_0_1].vertex_buffer_index = 2; + vertex_elems[VS_I_EB_0_1].vertex_buffer_index = 1; vertex_elems[VS_I_EB_0_1].src_format = PIPE_FORMAT_R32G32B32_FLOAT; /* y, cr, cb empty block element bottom left block */ - vertex_elems[VS_I_EB_1_0].src_offset = sizeof(float) * 6; + vertex_elems[VS_I_EB_1_0].src_offset = sizeof(float) * 8; vertex_elems[VS_I_EB_1_0].instance_divisor = 0; - vertex_elems[VS_I_EB_1_0].vertex_buffer_index = 2; + vertex_elems[VS_I_EB_1_0].vertex_buffer_index = 1; vertex_elems[VS_I_EB_1_0].src_format = PIPE_FORMAT_R32G32B32_FLOAT; /* y, cr, cb empty block element bottom right block */ - vertex_elems[VS_I_EB_1_1].src_offset = sizeof(float) * 9; + vertex_elems[VS_I_EB_1_1].src_offset = sizeof(float) * 11; vertex_elems[VS_I_EB_1_1].instance_divisor = 0; - vertex_elems[VS_I_EB_1_1].vertex_buffer_index = 2; + vertex_elems[VS_I_EB_1_1].vertex_buffer_index = 1; vertex_elems[VS_I_EB_1_1].src_format = PIPE_FORMAT_R32G32B32_FLOAT; /* progressive=0.0f interlaced=1.0f */ - vertex_elems[VS_I_INTERLACED].src_offset = sizeof(float) * 12; + vertex_elems[VS_I_INTERLACED].src_offset = sizeof(float) * 14; vertex_elems[VS_I_INTERLACED].instance_divisor = 0; - vertex_elems[VS_I_INTERLACED].vertex_buffer_index = 2; + vertex_elems[VS_I_INTERLACED].vertex_buffer_index = 1; vertex_elems[VS_I_INTERLACED].src_format = PIPE_FORMAT_R32_FLOAT; /* First ref surface top field texcoord element */ vertex_elems[VS_I_MV0].src_offset = 0; vertex_elems[VS_I_MV0].instance_divisor = 0; - vertex_elems[VS_I_MV0].vertex_buffer_index = 3; + vertex_elems[VS_I_MV0].vertex_buffer_index = 2; vertex_elems[VS_I_MV0].src_format = PIPE_FORMAT_R32G32_FLOAT; /* First ref surface bottom field texcoord element */ vertex_elems[VS_I_MV1].src_offset = 0; vertex_elems[VS_I_MV1].instance_divisor = 0; - vertex_elems[VS_I_MV1].vertex_buffer_index = 4; + vertex_elems[VS_I_MV1].vertex_buffer_index = 3; vertex_elems[VS_I_MV1].src_format = PIPE_FORMAT_R32G32_FLOAT; /* Second ref surface top field texcoord element */ vertex_elems[VS_I_MV2].src_offset = 0; vertex_elems[VS_I_MV2].instance_divisor = 0; - vertex_elems[VS_I_MV2].vertex_buffer_index = 5; + vertex_elems[VS_I_MV2].vertex_buffer_index = 4; vertex_elems[VS_I_MV2].src_format = PIPE_FORMAT_R32G32_FLOAT; /* Second ref surface bottom field texcoord element */ vertex_elems[VS_I_MV3].src_offset = 0; vertex_elems[VS_I_MV3].instance_divisor = 0; - vertex_elems[VS_I_MV3].vertex_buffer_index = 6; + vertex_elems[VS_I_MV3].vertex_buffer_index = 5; vertex_elems[VS_I_MV3].src_format = PIPE_FORMAT_R32G32_FLOAT; for(i = 0; i < VL_NUM_MACROBLOCK_TYPES; ++i) @@ -820,69 +815,56 @@ static void upload_vertex_stream(struct vl_mpeg12_mc_renderer *r, unsigned num_macroblocks[VL_NUM_MACROBLOCK_TYPES]) { - struct quadf *pos; - struct vertex_stream_0 *info; + struct vertex_stream_0 *pos; struct vertex2f *mv[4]; - struct pipe_transfer *buf_transfer[7]; + struct pipe_transfer *buf_transfer[5]; unsigned i, j; assert(r); assert(num_macroblocks); - pos = (struct quadf *)pipe_buffer_map + pos = (struct vertex_stream_0 *)pipe_buffer_map ( r->pipe, - r->vertex_bufs.individual.ycbcr.buffer, + r->vertex_bufs.individual.pos.buffer, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, &buf_transfer[0] ); - info = (struct vertex_stream_0 *)pipe_buffer_map - ( - r->pipe, - r->vertex_bufs.individual.info.buffer, - PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, - &buf_transfer[1] - ); - for (i = 0; i < 4; ++i) mv[i] = (struct vertex2f *)pipe_buffer_map ( r->pipe, r->vertex_bufs.individual.mv[i].buffer, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, - &buf_transfer[i + 2] + &buf_transfer[i + 1] ); for (i = 0; i < VL_NUM_MACROBLOCK_TYPES; ++i) { struct vl_mc_mbtype_handler *handler = &r->mbtype_handlers[i]; unsigned count = vl_vb_upload(&handler->pos, pos); if (count > 0) { + pos += count; + unsigned ref_frames, mv_per_frame; ref_frames = const_mbtype_config[i][0]; mv_per_frame = const_mbtype_config[i][1]; - pos += count; - - memcpy(info, handler->info, sizeof(struct vertex_stream_0) * count * 4); - info += count * 4; - for (j = 0; j < ref_frames * mv_per_frame; ++j) - memcpy(mv[j], handler->mv[j], sizeof(struct vertex2f) * count * 4); + vl_vb_upload(&handler->mv[j], mv[j]); for (j = 0; j < 4; ++j) - mv[j] += count * 4; + mv[j] += count; } num_macroblocks[i] = count; } - pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.ycbcr.buffer, buf_transfer[0]); - pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.info.buffer, buf_transfer[1]); + pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.pos.buffer, buf_transfer[0]); for (i = 0; i < 4; ++i) - pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.mv[i].buffer, buf_transfer[i + 2]); + pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.mv[i].buffer, buf_transfer[i + 1]); } static struct pipe_sampler_view @@ -926,7 +908,7 @@ flush_mbtype_handler(struct vl_mpeg12_mc_renderer *r, enum VL_MACROBLOCK_TYPE ty handler = &r->mbtype_handlers[type]; - r->pipe->set_vertex_buffers(r->pipe, 3 + ref_frames * mv_per_frame, r->vertex_bufs.all); + r->pipe->set_vertex_buffers(r->pipe, 2 + ref_frames * mv_per_frame, r->vertex_bufs.all); r->pipe->bind_vertex_elements_state(r->pipe, handler->vertex_elems_state); if(ref_frames == 2) { @@ -955,14 +937,14 @@ flush_mbtype_handler(struct vl_mpeg12_mc_renderer *r, enum VL_MACROBLOCK_TYPE ty r->pipe->bind_vs_state(r->pipe, handler->vs); r->pipe->bind_fs_state(r->pipe, handler->fs); - util_draw_arrays(r->pipe, PIPE_PRIM_QUADS, vb_start, num_macroblocks * 4); - return num_macroblocks * 4; + util_draw_arrays(r->pipe, PIPE_PRIM_QUADS, vb_start, num_macroblocks); + return num_macroblocks; } static void flush(struct vl_mpeg12_mc_renderer *r) { - unsigned num_macroblocks[VL_NUM_MACROBLOCK_TYPES] = { 0 }; + unsigned num_verts[VL_NUM_MACROBLOCK_TYPES] = { 0 }; unsigned vb_start = 0, i; assert(r); @@ -972,15 +954,15 @@ flush(struct vl_mpeg12_mc_renderer *r) vl_idct_flush(&r->idct_cr); vl_idct_flush(&r->idct_cb); - upload_vertex_stream(r, num_macroblocks); + upload_vertex_stream(r, num_verts); r->pipe->bind_rasterizer_state(r->pipe, r->rs_state); r->pipe->set_framebuffer_state(r->pipe, &r->fb_state); r->pipe->set_viewport_state(r->pipe, &r->viewport); for (i = 0; i < VL_NUM_MACROBLOCK_TYPES; ++i) { - if (num_macroblocks[i] > 0) - vb_start += flush_mbtype_handler(r, i, vb_start, num_macroblocks[i]); + if (num_verts[i] > 0) + vb_start += flush_mbtype_handler(r, i, vb_start, num_verts[i]); } r->pipe->flush(r->pipe, PIPE_FLUSH_RENDER_CACHE, r->fence); @@ -1114,9 +1096,10 @@ grab_vectors(struct vl_mpeg12_mc_renderer *r, handler = &r->mbtype_handlers[type]; - pos = handler->pos.num_blocks * 4; - vl_vb_add_block(&handler->pos, mb->mbx, mb->mby); + pos = handler->pos.num_verts; + info.pos.x = mb->mbx; + info.pos.y = mb->mby; for ( i = 0; i < 2; ++i) { for ( j = 0; j < 2; ++j) { info.eb[i][j].y = empty_block(r->chroma_format, mb->cbp, 0, j, i); @@ -1125,13 +1108,11 @@ grab_vectors(struct vl_mpeg12_mc_renderer *r, } } info.interlaced = mb->dct_type == PIPE_MPEG12_DCT_TYPE_FIELD ? 1.0f : 0.0f; + vl_vb_add_block(&handler->pos, (float*)&info); get_motion_vectors(mb, mv); - for ( i = 0; i < 4; ++i ) { - handler->info[i + pos] = info; - for ( j = 0; j < ref_frames * mv_per_frame; ++j ) - handler->mv[j][i + pos] = mv[j]; - } + for ( j = 0; j < ref_frames * mv_per_frame; ++j ) + vl_vb_add_block(&handler->mv[j], (float*)&mv[j]); } static void diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h index 9195718750d..fb169c7421e 100644 --- a/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h +++ b/src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.h @@ -59,24 +59,13 @@ enum VL_MACROBLOCK_TYPE VL_NUM_MACROBLOCK_TYPES }; -struct vertex_stream_0 -{ - struct { - float y; - float cr; - float cb; - } eb[2][2]; - float interlaced; -}; - struct vl_mc_mbtype_handler { void *vs, *fs; void *vertex_elems_state; struct vl_vertex_buffer pos; - struct vertex_stream_0 *info; - struct vertex2f *mv[4]; + struct vl_vertex_buffer mv[4]; }; struct vl_mpeg12_mc_renderer @@ -119,9 +108,9 @@ struct vl_mpeg12_mc_renderer union { - struct pipe_vertex_buffer all[7]; + struct pipe_vertex_buffer all[6]; struct { - struct pipe_vertex_buffer quad, ycbcr, info, mv[4]; + struct pipe_vertex_buffer quad, pos, mv[4]; } individual; } vertex_bufs; diff --git a/src/gallium/auxiliary/vl/vl_vertex_buffers.c b/src/gallium/auxiliary/vl/vl_vertex_buffers.c index 6df11db0aef..dba69f9a6a2 100644 --- a/src/gallium/auxiliary/vl/vl_vertex_buffers.c +++ b/src/gallium/auxiliary/vl/vl_vertex_buffers.c @@ -82,27 +82,28 @@ vl_vb_upload_quads(struct pipe_context *pipe, unsigned max_blocks) } bool -vl_vb_init(struct vl_vertex_buffer *buffer, unsigned max_blocks) +vl_vb_init(struct vl_vertex_buffer *buffer, unsigned max_blocks, unsigned num_elements) { assert(buffer); - buffer->num_blocks = 0; - buffer->blocks = MALLOC(max_blocks * sizeof(struct quadf)); - return buffer->blocks != NULL; + buffer->num_verts = 0; + buffer->num_elements = num_elements; + buffer->buffer = MALLOC(max_blocks * num_elements * sizeof(float) * 4); + return buffer->buffer != NULL; } unsigned -vl_vb_upload(struct vl_vertex_buffer *buffer, struct quadf *dst) +vl_vb_upload(struct vl_vertex_buffer *buffer, void *dst) { unsigned todo; assert(buffer); - todo = buffer->num_blocks; - buffer->num_blocks = 0; + todo = buffer->num_verts; + buffer->num_verts = 0; if(todo) - memcpy(dst, buffer->blocks, sizeof(struct quadf) * todo); + memcpy(dst, buffer->buffer, sizeof(float) * buffer->num_elements * todo); return todo; } @@ -112,5 +113,5 @@ vl_vb_cleanup(struct vl_vertex_buffer *buffer) { assert(buffer); - FREE(buffer->blocks); + FREE(buffer->buffer); } diff --git a/src/gallium/auxiliary/vl/vl_vertex_buffers.h b/src/gallium/auxiliary/vl/vl_vertex_buffers.h index fa4ec1dedd8..8d7c0e6a275 100644 --- a/src/gallium/auxiliary/vl/vl_vertex_buffers.h +++ b/src/gallium/auxiliary/vl/vl_vertex_buffers.h @@ -33,28 +33,31 @@ struct vl_vertex_buffer { - unsigned num_blocks; - struct quadf *blocks; + unsigned num_verts; + unsigned num_elements; + float *buffer; }; struct pipe_vertex_buffer vl_vb_upload_quads(struct pipe_context *pipe, unsigned max_blocks); -bool vl_vb_init(struct vl_vertex_buffer *buffer, unsigned max_blocks); +bool vl_vb_init(struct vl_vertex_buffer *buffer, unsigned max_blocks, unsigned num_elements); static inline void -vl_vb_add_block(struct vl_vertex_buffer *buffer, signed x, signed y) +vl_vb_add_block(struct vl_vertex_buffer *buffer, float *elements) { - struct quadf *quad; + float *pos; + unsigned i; assert(buffer); - quad = buffer->blocks + buffer->num_blocks; - quad->bl.x = quad->tl.x = quad->tr.x = quad->br.x = x; - quad->bl.y = quad->tl.y = quad->tr.y = quad->br.y = y; - buffer->num_blocks++; + for(i = 0; i < 4; ++i) { + pos = buffer->buffer + buffer->num_verts * buffer->num_elements; + memcpy(pos, elements, sizeof(float) * buffer->num_elements); + buffer->num_verts++; + } } -unsigned vl_vb_upload(struct vl_vertex_buffer *buffer, struct quadf *dst); +unsigned vl_vb_upload(struct vl_vertex_buffer *buffer, void *dst); void vl_vb_cleanup(struct vl_vertex_buffer *buffer); |