void process(const YV12Image &in_data, const YV12Image &out_data) { // (1) Fill the format descriptors for the top and bottom fields. The same // context can not be used for both fields, as they are located at opposite // offsets from the image center. If the fields were to be scaled as // progressive-scan images of half height, spatial misalignment of the // output would occur. zimgxx::zimage_format in_format_t = get_image_format(in_data, true); zimgxx::zimage_format in_format_b = get_image_format(in_data, false); zimgxx::zimage_format out_format_t = get_image_format(out_data, true); zimgxx::zimage_format out_format_b = get_image_format(out_data, false); // (2) Build the processing contexts. zimgxx::FilterGraph graph_t{ zimgxx::FilterGraph::build(in_format_t, out_format_t) }; zimgxx::FilterGraph graph_b{ zimgxx::FilterGraph::build(in_format_b, out_format_b) }; // (3) Allocate scanline and temporary buffers for input and output data. In // this case, the same buffers can be used for both fields. unsigned input_buffering_t = graph_t.get_input_buffering(); unsigned input_buffering_b = graph_b.get_input_buffering(); unsigned output_buffering_t = graph_t.get_input_buffering(); unsigned output_buffering_b = graph_b.get_input_buffering(); size_t tmp_size_t = graph_t.get_tmp_size(); size_t tmp_size_b = graph_b.get_tmp_size(); std::cout << "input buffering: " << std::max(input_buffering_t, input_buffering_b) << '\n'; std::cout << "output buffering: " << std::max(output_buffering_t, output_buffering_b) << '\n'; std::cout << "heap usage: " << std::max(tmp_size_t, tmp_size_b) << '\n'; auto in_buf = allocate_buffer(in_format_t, std::max(input_buffering_t, input_buffering_b)); auto out_buf = allocate_buffer(out_format_t, std::max(output_buffering_t, output_buffering_b)); auto tmp_buf = allocate_buffer(std::max(tmp_size_t, tmp_size_b)); // (4) Store context information required by the I/O callbacks. The // callbacks convert between the on-disk and z.lib alignment requirements. Callback unpack_data = { &in_buf.first, &in_data, false, true }; Callback pack_data = { &out_buf.first, &out_data, true, true }; // (5) Process the top field. graph_t.process(in_buf.first.as_const(), out_buf.first, tmp_buf.get(), yv12_bitblt_callback, &unpack_data, yv12_bitblt_callback, &pack_data); // (6) Process the bottom field. unpack_data.top_field = false; pack_data.top_field = false; graph_b.process(in_buf.first.as_const(), out_buf.first, tmp_buf.get(), yv12_bitblt_callback, &unpack_data, yv12_bitblt_callback, &pack_data); }
static bool run_test(GLbitfield shaders) { const struct grid_info grid = { shaders, get_image_format(GL_R32UI), { W, H, 1, 1 } }; const struct image_info img = image_info_for_grid(grid); GLuint prog = generate_program( grid, GL_VERTEX_SHADER, generate_source(grid, img, GL_VERTEX_SHADER), GL_TESS_CONTROL_SHADER, generate_source(grid, img, GL_TESS_CONTROL_SHADER), GL_TESS_EVALUATION_SHADER, generate_source(grid, img, GL_TESS_EVALUATION_SHADER), GL_GEOMETRY_SHADER, generate_source(grid, img, GL_GEOMETRY_SHADER), GL_FRAGMENT_SHADER, generate_source(grid, img, GL_FRAGMENT_SHADER), GL_COMPUTE_SHADER, generate_source(grid, img, GL_COMPUTE_SHADER)); bool ret = prog && init_fb(grid) && init_images(img) && bind_images(grid, prog) && draw_grid(grid, prog) && check(grid, img); glDeleteProgram(prog); return ret; }
static bool run_test(const struct image_target_info *target, const struct image_extent size) { const struct grid_info grid = { GL_FRAGMENT_SHADER_BIT, get_image_format(GL_RGBA32F), image_optimal_extent(size) }; const struct image_info img = { target, grid.format, size, image_format_epsilon(grid.format) }; GLuint prog = generate_program( grid, GL_FRAGMENT_SHADER, concat(image_hunk(img, ""), hunk("readonly uniform IMAGE_T src_img;\n" "writeonly uniform IMAGE_T dst_img;\n" "\n" "GRID_T op(ivec2 idx, GRID_T x) {\n" " imageStore(dst_img, IMAGE_ADDR(idx)," " imageLoad(src_img, IMAGE_ADDR(idx)));\n" " return x;\n" "}\n"), NULL)); bool ret = prog && init_fb(grid) && init_image(img, 0) && init_image(img, 1) && set_uniform_int(prog, "src_img", 0) && set_uniform_int(prog, "dst_img", 1) && draw_grid(grid, prog) && check(img); glDeleteProgram(prog); return ret; }
static bool run_test(const struct image_qualifier_info *qual, const struct image_stage_info *stage_w, const struct image_stage_info *stage_r, unsigned l) { const struct grid_info grid = { stage_w->bit | stage_r->bit, get_image_format(GL_RGBA32UI), { l, l, 1, 1 } }; const struct image_info img = image_info_for_grid(grid); GLuint prog = generate_program( grid, /* * Write (11, 22, 33, 44) to some location on the * image from the write stage. */ stage_w->stage, concat(qualifier_hunk(qual), image_hunk(img, ""), hunk("IMAGE_Q uniform IMAGE_T img;\n" "\n" "GRID_T op(ivec2 idx, GRID_T x) {\n" " imageStore(img, idx, DATA_T(11, 22, 33, 44));" " return x;" "}\n"), NULL), /* * The same location will read back the expected value * if image access is coherent, as the shader inputs * of the read stage are dependent on the outputs of * the write stage and consequently they are * guaranteed to be executed sequentially. */ stage_r->stage, concat(qualifier_hunk(qual), image_hunk(img, ""), hunk("IMAGE_Q uniform IMAGE_T img;\n" "\n" "GRID_T op(ivec2 idx, GRID_T x) {\n" " DATA_T v = imageLoad(img, idx);" " if (v == DATA_T(11, 22, 33, 44))" " return GRID_T(33, 33, 33, 33);" " else" " return GRID_T(77, 77, 77, 77);" "}\n"), NULL)); bool ret = prog && init_fb(grid) && init_image(img) && set_uniform_int(prog, "img", 0) && draw_grid(grid, prog) && (check(grid, img) || qual->control_test); glDeleteProgram(prog); return ret; }
void GLAPIENTRY _mesa_BindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) { GET_CURRENT_CONTEXT(ctx); struct gl_texture_object *t = NULL; struct gl_image_unit *u; if (!validate_bind_image_texture(ctx, unit, texture, level, layered, layer, access, format)) return; u = &ctx->ImageUnits[unit]; FLUSH_VERTICES(ctx, 0); ctx->NewDriverState |= ctx->DriverFlags.NewImageUnits; if (texture) { t = _mesa_lookup_texture(ctx, texture); if (!t) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(texture)"); return; } _mesa_reference_texobj(&u->TexObj, t); u->Level = level; u->Access = access; u->Format = format; u->_ActualFormat = get_image_format(format); if (_mesa_tex_target_is_layered(t->Target)) { u->Layered = layered; u->Layer = (layered ? 0 : layer); } else { u->Layered = GL_FALSE; u->Layer = 0; } } else { _mesa_reference_texobj(&u->TexObj, NULL); } u->_Valid = validate_image_unit(ctx, u); if (ctx->Driver.BindImageTexture) ctx->Driver.BindImageTexture(ctx, u, t, level, layered, layer, access, format); }
int load_image_f(char * fname,FILE * f,mgfx_image_t ** the_img) { struct mgfx_image_format * fmt; mgfx_image_t * img; int __ret; if(!(img=(mgfx_image_t *)malloc(sizeof(mgfx_image_t)))) return _PICERR_NOMEM; if(!(fmt=get_image_format(fname))) return _PICERR_UNSUPPORTED; img->fmt=fmt; __ret=fmt->load_fn(f,img); if(__ret==_PIC_OK) { *the_img=img; } else { *the_img=NULL; free(img); } fclose(f); return __ret; }
/** * Execute the given action. */ static bool exec_action(const struct image_unit_action a) { if (a.action == BIND_NEW) { const GLenum format = (get_image_format(a.format) ? a.format : GL_RGBA32F); const struct image_info img = image_info(a.obj, format, W, H); const unsigned num_levels = image_num_levels(img); uint32_t pixels[4 * N * M] = { 0 }; if (!upload_image_levels(img, num_levels, 0, a.idx, pixels)) return false; glBindImageTexture(a.idx, get_texture(a.idx), a.level, a.layered, a.layer, a.access, a.format); } else if (a.action == BIND_IDX) { const unsigned idx = MIN2(a.idx, max_image_units()); glBindImageTexture(idx, get_texture(a.obj), a.level, a.layered, a.layer, a.access, a.format); } else if (a.action == BIND_OBJ) { glBindImageTexture(a.idx, a.obj, a.level, a.layered, a.layer, a.access, a.format); } else if (a.action == DELETE_IDX) { GLuint tex = get_texture(a.idx); glDeleteTextures(1, &tex); } else { abort(); } return piglit_check_gl_error(a.expect_status); }
static bool check_derivative(const struct grid_info grid, const struct image_info img, unsigned w, unsigned h) { uint32_t pixels_fb[H][W], expect_fb[H][W]; uint32_t pixels_img[H][W], expect_img[H][W]; int i, j; for (i = 0; i < W; ++i) { for (j = 0; j < H; ++j) { expect_fb[j][i] = (j < h && i < w ? 1000 : encode(get_image_format(GL_R32F), 0.5)); expect_img[j][i] = (j < h && i < w ? 1 : 0) + j; } } if (!download_result(grid, pixels_fb[0]) || !download_image(img, 0, pixels_img[0])) return false; if (!check_pixels_v(img, pixels_fb[0], expect_fb[0])) { printf(" Source: framebuffer\n"); /* * Purely informational check, we don't care what the * result is as long as derivatives are being * calculated, don't fail if the result doesn't equal * the expected value as it's most likely an accuracy * issue. */ } if (!check_pixels_v(img, pixels_img[0], expect_img[0])) { printf(" Source: image\n"); return false; } return true; }
static GLboolean validate_bind_image_texture(struct gl_context *ctx, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) { assert(ctx->Const.MaxImageUnits <= MAX_IMAGE_UNITS); if (unit >= ctx->Const.MaxImageUnits) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(unit)"); return GL_FALSE; } if (level < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(level)"); return GL_FALSE; } if (layer < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(layer)"); return GL_FALSE; } if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(access)"); return GL_FALSE; } if (!get_image_format(format)) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindImageTexture(format)"); return GL_FALSE; } return GL_TRUE; }
int get_image(VASurfaceID surface, Image *dst_img) { VAAPIContext * const vaapi = vaapi_get_context(); VAImage image; VAImageFormat *image_format = NULL; VAStatus status; Image bound_image; int i, is_bound_image = 0, is_derived_image = 0, error = -1; image.image_id = VA_INVALID_ID; image.buf = VA_INVALID_ID; if (!image_format) { status = vaDeriveImage(vaapi->display, surface, &image); if (vaapi_check_status(status, "vaDeriveImage()")) { if (image.image_id != VA_INVALID_ID && image.buf != VA_INVALID_ID) { D(bug("using vaDeriveImage()\n")); is_derived_image = 1; image_format = &image.format; } else { D(bug("vaDeriveImage() returned success but VA image is invalid. Trying vaGetImage()\n")); } } } if (!image_format) { for (i = 0; image_formats[i] != 0; i++) { if (get_image_format(vaapi, image_formats[i], &image_format)) break; } } if (!image_format) goto end; D(bug("selected %s image format for getimage\n", string_of_VAImageFormat(image_format))); if (!is_derived_image) { status = vaCreateImage(vaapi->display, image_format, vaapi->picture_width, vaapi->picture_height, &image); if (!vaapi_check_status(status, "vaCreateImage()")) goto end; D(bug("created image with id 0x%08x and buffer id 0x%08x\n", image.image_id, image.buf)); VARectangle src_rect; src_rect.x = 0; src_rect.y = 0; src_rect.width = vaapi->picture_width; src_rect.height = vaapi->picture_height; D(bug("src rect (%d,%d):%ux%u\n", src_rect.x, src_rect.y, src_rect.width, src_rect.height)); status = vaGetImage( vaapi->display, vaapi->surface_id, src_rect.x, src_rect.y, src_rect.width, src_rect.height, image.image_id ); if (!vaapi_check_status(status, "vaGetImage()")) { vaDestroyImage(vaapi->display, image.image_id); goto end; } } if (bind_image(&image, &bound_image) < 0) goto end; is_bound_image = 1; if (image_convert(dst_img, &bound_image) < 0) goto end; error = 0; end: if (is_bound_image) { if (release_image(&image) < 0) error = -1; } if (image.image_id != VA_INVALID_ID) { status = vaDestroyImage(vaapi->display, image.image_id); if (!vaapi_check_status(status, "vaDestroyImage()")) error = -1; } return error; }