Lines Matching +full:device +full:- +full:width
2 * QEMU Apple ParavirtualizedGraphics.framework device
6 * SPDX-License-Identifier: GPL-2.0-or-later
10 * proprietary guest communication channel to drive it. This device model
20 #include "block/aio-wait.h"
21 #include "system/address-spaces.h"
25 #include "apple-gfx.h"
48 /* ------ PGTask and task operations: new/destroy/map/unmap ------ */
56 * A "task" in PVG terminology represents a host-virtual contiguous address
60 * This type of operation isn't well-supported by QEMU's memory subsystem,
94 task->s = s;
95 task->address = task_mem;
96 task->len = len;
97 task->mapped_regions = g_ptr_array_sized_new(2 /* Usually enough */);
99 QEMU_LOCK_GUARD(&s->task_mutex);
100 QTAILQ_INSERT_TAIL(&s->tasks, task, node);
107 GPtrArray *regions = task->mapped_regions;
111 for (i = 0; i < regions->len; ++i) {
117 mach_vm_deallocate(mach_task_self(), task->address, task->len);
119 QEMU_LOCK_GUARD(&s->task_mutex);
120 QTAILQ_REMOVE(&s->tasks, task, node);
167 QEMU_LOCK_GUARD(&s->task_mutex);
173 target = task->address + virtual_offset;
174 virtual_offset += range->physicalLength;
176 trace_apple_gfx_map_memory_range(i, range->physicalAddress,
177 range->physicalLength);
180 source_ptr = apple_gfx_host_ptr_for_gpa_range(range->physicalAddress,
181 range->physicalLength,
188 if (!g_ptr_array_find(task->mapped_regions, region, NULL)) {
189 g_ptr_array_add(task->mapped_regions, region);
195 /* Map guest RAM at range->physicalAddress into PG task memory range */
197 &target, range->physicalLength, vm_page_size - 1,
222 range_address = task->address + virtual_offset;
228 /* ------ Rendering and frame management ------ */
234 bool managed_texture = s->using_managed_texture_storage;
235 uint32_t width = surface_width(s->surface);
236 uint32_t height = surface_height(s->surface);
237 MTLRegion region = MTLRegionMake2D(0, 0, width, height);
238 id<MTLCommandBuffer> command_buffer = [s->mtl_queue commandBuffer];
239 id<MTLTexture> texture = s->texture;
245 s->rendering_frame_width = width;
246 s->rendering_frame_height = height;
250 * This is not safe to call from the BQL/BH due to PVG-internal locks
253 bool r = [s->pgdisp encodeCurrentFrameToCommandBuffer:command_buffer
263 --s->pending_frames;
264 if (s->pending_frames > 0) {
292 * TODO: Skip this entirely on a pure Metal or headless/guest-only
296 size_t width = texture.width, height = texture.height;
297 MTLRegion region = MTLRegionMake2D(0, 0, width, height);
299 bytesPerRow:(width * 4)
300 bytesPerImage:(width * height * 4)
311 --s->pending_frames;
312 assert(s->pending_frames >= 0);
315 if (s->rendering_frame_width == surface_width(s->surface) &&
316 s->rendering_frame_height == surface_height(s->surface)) {
317 copy_mtl_texture_to_surface_mem(s->texture, surface_data(s->surface));
318 if (s->gfx_update_requested) {
319 s->gfx_update_requested = false;
320 dpy_gfx_update_full(s->con);
321 graphic_hw_update_done(s->con);
322 s->new_frame_ready = false;
324 s->new_frame_ready = true;
327 if (s->pending_frames > 0) {
338 if (s->new_frame_ready) {
339 dpy_gfx_update_full(s->con);
340 s->new_frame_ready = false;
341 graphic_hw_update_done(s->con);
342 } else if (s->pending_frames > 0) {
343 s->gfx_update_requested = true;
345 graphic_hw_update_done(s->con);
354 /* ------ Mouse cursor and display mode setting ------ */
356 static void set_mode(AppleGFXState *s, uint32_t width, uint32_t height)
360 if (s->surface &&
361 width == surface_width(s->surface) &&
362 height == surface_height(s->surface)) {
366 [s->texture release];
368 s->surface = qemu_create_displaysurface(width, height);
374 width:width
377 textureDescriptor.usage = s->pgdisp.minimumTextureUsage;
378 s->texture = [s->mtl newTextureWithDescriptor:textureDescriptor];
379 s->using_managed_texture_storage =
380 (s->texture.storageMode == MTLStorageModeManaged);
383 dpy_gfx_replace_surface(s->con, s->surface);
389 dpy_mouse_set(s->con, s->pgdisp.cursorPosition.x,
390 s->pgdisp.cursorPosition.y, qatomic_read(&s->cursor_show));
408 AppleGFXState *s = job->s;
409 NSBitmapImageRep *glyph = job->glyph;
411 size_t width = glyph.pixelsWide;
413 size_t padding_bytes_per_row = glyph.bytesPerRow - width * 4;
416 trace_apple_gfx_cursor_set(bpp, width, height);
418 if (s->cursor) {
419 cursor_unref(s->cursor);
420 s->cursor = NULL;
424 s->cursor = cursor_alloc(width, height);
425 s->cursor->hot_x = job->hotspot.x;
426 s->cursor->hot_y = job->hotspot.y;
428 uint32_t *dest_px = s->cursor->data;
431 for (size_t x = 0; x < width; ++x) {
446 dpy_cursor_define(s->con, s->cursor);
454 /* ------ DMA (device reading system memory) ------ */
469 r = dma_memory_read(&address_space_memory, job->physical_address,
470 job->dst, job->length, MEMTXATTRS_UNSPECIFIED);
471 job->success = (r == MEMTX_OK);
473 qemu_event_set(&job->event);
494 /* ------ Memory-mapped device I/O operations ------ */
506 job->value = [job->state->pgdev mmioReadAtOffset:job->offset];
507 qatomic_set(&job->completed, true);
530 [job->state->pgdev mmioWriteAtOffset:job->offset value:job->value];
531 qatomic_set(&job->completed, true);
586 /* ------ Initialisation and startup ------ */
593 memory_region_init_io(&s->iomem_gfx, obj, &apple_gfx_ops, s, obj_name,
596 /* TODO: PVG framework supports serialising device state: integrate it! */
604 *baseAddress = (void *)task->address;
610 trace_apple_gfx_destroy_task(task, task->mapped_regions->len);
639 if (s->pending_frames >= 2) {
642 ++s->pending_frames;
643 if (s->pending_frames > 1) {
673 job->s = s;
674 job->glyph = glyph;
675 job->hotspot = hotspot;
682 qatomic_set(&s->cursor_show, show);
704 trace_apple_gfx_display_mode(i, mode->width_px, mode->height_px);
705 PGDisplayCoord_t mode_size = { mode->width_px, mode->height_px };
709 refreshRateInHz:mode->refresh_rate_hz];
722 /* Prefer a unified memory GPU. Failing that, pick a non-removable GPU. */
753 "Migration state blocked by apple-gfx display device");
759 qemu_mutex_init(&s->task_mutex);
760 QTAILQ_INIT(&s->tasks);
761 s->mtl = copy_suitable_metal_device();
762 s->mtl_queue = [s->mtl newCommandQueue];
764 desc.device = s->mtl;
768 s->cursor_show = true;
770 s->pgdev = PGNewDeviceWithDescriptor(desc);
775 * multiple virtual displays connected to a single PV graphics device.
777 * more than one instance of the device, each with one display. The macOS
781 s->pgdisp = [s->pgdev newDisplayWithDescriptor:disp_desc
786 if (s->display_modes != NULL && s->num_display_modes > 0) {
787 trace_apple_gfx_common_realize_modes_property(s->num_display_modes);
788 display_modes = s->display_modes;
789 num_display_modes = s->num_display_modes;
791 s->pgdisp.modeList = mode_array =
795 s->con = graphic_console_init(dev, 0, &apple_gfx_fb_ops, s);
799 /* ------ Display mode list device property ------ */
813 mode->width_px, mode->height_px,
814 mode->refresh_rate_hz);
839 error_setg(errp, "width in '%s' must be a decimal integer number"
843 mode->width_px = val;
854 mode->height_px = val;
865 mode->refresh_rate_hz = val;
870 "Each display mode takes the format '<width>x<height>@<rate>'");
876 "Display mode in pixels and Hertz, as <width>x<height>@<refresh-rate> "