Changeset 104834 in vbox
- Timestamp:
- Jun 4, 2024 2:37:41 PM (9 months ago)
- svn:sync-xref-src-repo-rev:
- 163414
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/Graphics/VBoxVideoGuest.h
r98103 r104834 98 98 uint8_t *pPixels, 99 99 uint32_t cbLength); 100 DECLHIDDEN(int) VBoxHGSMI CursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition, uint32_t x, uint32_t y,101 uint32_t *pxHost, uint32_t *pyHost);100 DECLHIDDEN(int) VBoxHGSMIReportCursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition, uint32_t x, uint32_t y, 101 uint32_t *pxHost, uint32_t *pyHost); 102 102 103 103 /** @} */ -
trunk/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp
r98103 r104834 256 256 * @returns VERR_NO_MEMORY HGSMI heap allocation failed. 257 257 */ 258 DECLHIDDEN(int) VBoxHGSMI CursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition,259 uint32_t x, uint32_t y, uint32_t *pxHost, uint32_t *pyHost)258 DECLHIDDEN(int) VBoxHGSMIReportCursorPosition(PHGSMIGUESTCOMMANDCONTEXT pCtx, bool fReportPosition, 259 uint32_t x, uint32_t y, uint32_t *pxHost, uint32_t *pyHost) 260 260 { 261 261 VBVACURSORPOSITION *p; -
trunk/src/VBox/Additions/linux/drm/vbox_mode.c
r102874 r104834 58 58 59 59 static int vbox_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv, 60 61 60 u32 handle, u32 width, u32 height, 61 s32 hot_x, s32 hot_y); 62 62 static int vbox_cursor_move(struct drm_crtc *crtc, int x, int y); 63 63 … … 67 67 */ 68 68 static void vbox_do_modeset(struct drm_crtc *crtc, 69 70 { 71 72 73 74 75 76 77 78 79 69 const struct drm_display_mode *mode) 70 { 71 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc); 72 struct vbox_private *vbox; 73 int width, height, bpp, pitch; 74 u16 flags; 75 s32 x_offset, y_offset; 76 77 vbox = crtc->dev->dev_private; 78 width = mode->hdisplay ? mode->hdisplay : 640; 79 height = mode->vdisplay ? mode->vdisplay : 480; 80 80 #if RTLNX_VER_MIN(4,11,0) || RTLNX_RHEL_MAJ_PREREQ(7,5) 81 82 81 bpp = crtc->enabled ? CRTC_FB(crtc)->format->cpp[0] * 8 : 32; 82 pitch = crtc->enabled ? CRTC_FB(crtc)->pitches[0] : width * bpp / 8; 83 83 #elif RTLNX_VER_MIN(3,3,0) 84 85 86 #else 87 88 89 #endif 90 91 92 93 94 95 96 97 98 99 100 101 102 103 84 bpp = crtc->enabled ? CRTC_FB(crtc)->bits_per_pixel : 32; 85 pitch = crtc->enabled ? CRTC_FB(crtc)->pitches[0] : width * bpp / 8; 86 #else 87 bpp = crtc->enabled ? CRTC_FB(crtc)->bits_per_pixel : 32; 88 pitch = crtc->enabled ? CRTC_FB(crtc)->pitch : width * bpp / 8; 89 #endif 90 x_offset = vbox->single_framebuffer ? crtc->x : vbox_crtc->x_hint; 91 y_offset = vbox->single_framebuffer ? crtc->y : vbox_crtc->y_hint; 92 93 /* 94 * This is the old way of setting graphics modes. It assumed one screen 95 * and a frame-buffer at the start of video RAM. On older versions of 96 * VirtualBox, certain parts of the code still assume that the first 97 * screen is programmed this way, so try to fake it. 98 */ 99 if (vbox_crtc->crtc_id == 0 && crtc->enabled && 100 vbox_crtc->fb_offset / pitch < 0xffff - crtc->y && 101 vbox_crtc->fb_offset % (bpp / 8) == 0) 102 VBoxVideoSetModeRegisters( 103 width, height, pitch * 8 / bpp, 104 104 #if RTLNX_VER_MIN(4,11,0) || RTLNX_RHEL_MAJ_PREREQ(7,5) 105 106 #else 107 108 #endif 109 110 111 112 113 114 115 116 117 118 119 120 121 105 CRTC_FB(crtc)->format->cpp[0] * 8, 106 #else 107 CRTC_FB(crtc)->bits_per_pixel, 108 #endif 109 0, 110 vbox_crtc->fb_offset % pitch / bpp * 8 + crtc->x, 111 vbox_crtc->fb_offset / pitch + crtc->y); 112 113 flags = VBVA_SCREEN_F_ACTIVE; 114 flags |= (crtc->enabled && !vbox_crtc->blanked) ? 115 0 : VBVA_SCREEN_F_BLANK; 116 flags |= vbox_crtc->disconnected ? VBVA_SCREEN_F_DISABLED : 0; 117 VBoxHGSMIProcessDisplayInfo(vbox->guest_pool, vbox_crtc->crtc_id, 118 x_offset, y_offset, vbox_crtc->fb_offset + 119 crtc->x * bpp / 8 + crtc->y * pitch, 120 pitch, width, height, 121 vbox_crtc->blanked ? 0 : bpp, flags); 122 122 } 123 123 124 124 static void vbox_crtc_dpms(struct drm_crtc *crtc, int mode) 125 125 { 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 126 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc); 127 struct vbox_private *vbox = crtc->dev->dev_private; 128 129 switch (mode) { 130 case DRM_MODE_DPMS_ON: 131 vbox_crtc->blanked = false; 132 /* Restart the refresh timer if necessary. */ 133 schedule_delayed_work(&vbox->refresh_work, VBOX_REFRESH_PERIOD); 134 break; 135 case DRM_MODE_DPMS_STANDBY: 136 case DRM_MODE_DPMS_SUSPEND: 137 case DRM_MODE_DPMS_OFF: 138 vbox_crtc->blanked = true; 139 break; 140 } 141 142 mutex_lock(&vbox->hw_mutex); 143 vbox_do_modeset(crtc, &crtc->hwmode); 144 mutex_unlock(&vbox->hw_mutex); 145 145 } 146 146 147 147 static bool vbox_crtc_mode_fixup(struct drm_crtc *crtc, 148 149 150 { 151 148 const struct drm_display_mode *mode, 149 struct drm_display_mode *adjusted_mode) 150 { 151 return true; 152 152 } 153 153 … … 159 159 static bool vbox_set_up_input_mapping(struct vbox_private *vbox) 160 160 { 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 161 struct drm_crtc *crtci; 162 struct drm_connector *connectori; 163 struct drm_framebuffer *fb1 = NULL; 164 bool single_framebuffer = true; 165 bool old_single_framebuffer = vbox->single_framebuffer; 166 u16 width = 0, height = 0; 167 168 /* 169 * Are we using an X.Org-style single large frame-buffer for all crtcs? 170 * If so then screen layout can be deduced from the crtc offsets. 171 * Same fall-back if this is the fbdev frame-buffer. 172 */ 173 list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list, head) { 174 if (!fb1) { 175 fb1 = CRTC_FB(crtci); 176 if (to_vbox_framebuffer(fb1) == &vbox->fbdev->afb) 177 break; 178 } else if (CRTC_FB(crtci) && fb1 != CRTC_FB(crtci)) { 179 single_framebuffer = false; 180 } 181 } 182 if (single_framebuffer) { 183 list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list, 184 head) { 185 if (to_vbox_crtc(crtci)->crtc_id != 0) 186 continue; 187 188 if (!CRTC_FB(crtci)) 189 break; 190 vbox->single_framebuffer = true; 191 vbox->input_mapping_width = CRTC_FB(crtci)->width; 192 vbox->input_mapping_height = CRTC_FB(crtci)->height; 193 return old_single_framebuffer != 194 vbox->single_framebuffer; 195 } 196 } 197 /* Otherwise calculate the total span of all screens. */ 198 list_for_each_entry(connectori, &vbox->dev->mode_config.connector_list, 199 head) { 200 struct vbox_connector *vbox_connector = 201 to_vbox_connector(connectori); 202 struct vbox_crtc *vbox_crtc = vbox_connector->vbox_crtc; 203 204 width = max_t(u16, width, vbox_crtc->x_hint + 205 vbox_connector->mode_hint.width); 206 height = max_t(u16, height, vbox_crtc->y_hint + 207 vbox_connector->mode_hint.height); 208 } 209 210 vbox->single_framebuffer = false; 211 vbox->input_mapping_width = width; 212 vbox->input_mapping_height = height; 213 214 return old_single_framebuffer != vbox->single_framebuffer; 215 215 } 216 216 217 217 static int vbox_crtc_set_base(struct drm_crtc *crtc, 218 219 220 221 { 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 218 struct drm_framebuffer *old_fb, 219 struct drm_framebuffer *new_fb, 220 int x, int y) 221 { 222 struct vbox_private *vbox = crtc->dev->dev_private; 223 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc); 224 struct drm_gem_object *obj; 225 struct vbox_framebuffer *vbox_fb; 226 struct vbox_bo *bo; 227 int ret; 228 u64 gpu_addr; 229 230 vbox_fb = to_vbox_framebuffer(new_fb); 231 obj = vbox_fb->obj; 232 bo = gem_to_vbox_bo(obj); 233 234 ret = vbox_bo_reserve(bo, false); 235 if (ret) 236 return ret; 237 238 ret = vbox_bo_pin(bo, VBOX_MEM_TYPE_VRAM, &gpu_addr); 239 vbox_bo_unreserve(bo); 240 if (ret) 241 return ret; 242 243 /* Unpin the previous fb. Do this after the new one has been pinned rather 244 * than before and re-pinning it on failure in case that fails too. */ 245 if (old_fb) { 246 vbox_fb = to_vbox_framebuffer(old_fb); 247 obj = vbox_fb->obj; 248 bo = gem_to_vbox_bo(obj); 249 ret = vbox_bo_reserve(bo, false); 250 /* This should never fail, as no one else should be accessing it and we 251 * should be running under the modeset locks. */ 252 if (!ret) { 253 vbox_bo_unpin(bo); 254 vbox_bo_unreserve(bo); 255 } 256 else 257 { 258 DRM_ERROR("unable to lock buffer object: error %d\n", ret); 259 } 260 } 261 262 if (&vbox->fbdev->afb == vbox_fb) 263 vbox_fbdev_set_base(vbox, gpu_addr); 264 265 vbox_crtc->fb_offset = gpu_addr; 266 if (vbox_set_up_input_mapping(vbox)) { 267 struct drm_crtc *crtci; 268 269 list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list, 270 head) { 271 vbox_do_modeset(crtci, &crtci->mode); 272 } 273 } 274 275 return 0; 276 276 } 277 277 278 278 static int vbox_crtc_mode_set(struct drm_crtc *crtc, 279 280 281 282 { 283 284 285 286 287 288 289 290 291 292 293 294 279 struct drm_display_mode *mode, 280 struct drm_display_mode *adjusted_mode, 281 int x, int y, struct drm_framebuffer *old_fb) 282 { 283 struct vbox_private *vbox = crtc->dev->dev_private; 284 int ret = vbox_crtc_set_base(crtc, old_fb, CRTC_FB(crtc), x, y); 285 if (ret) 286 return ret; 287 mutex_lock(&vbox->hw_mutex); 288 vbox_do_modeset(crtc, mode); 289 VBoxHGSMIUpdateInputMapping(vbox->guest_pool, 0, 0, 290 vbox->input_mapping_width, 291 vbox->input_mapping_height); 292 mutex_unlock(&vbox->hw_mutex); 293 294 return ret; 295 295 } 296 296 297 297 static int vbox_crtc_page_flip(struct drm_crtc *crtc, 298 298 struct drm_framebuffer *fb, 299 299 #if RTLNX_VER_MIN(4,12,0) || RTLNX_RHEL_MAJ_PREREQ(7,5) 300 301 302 300 struct drm_pending_vblank_event *event, 301 uint32_t page_flip_flags, 302 struct drm_modeset_acquire_ctx *ctx) 303 303 #elif RTLNX_VER_MIN(3,12,0) || RTLNX_RHEL_MAJ_PREREQ(7,0) 304 305 306 #else 307 308 #endif 309 { 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 304 struct drm_pending_vblank_event *event, 305 uint32_t page_flip_flags) 306 #else 307 struct drm_pending_vblank_event *event) 308 #endif 309 { 310 struct vbox_private *vbox = crtc->dev->dev_private; 311 struct drm_device *drm = vbox->dev; 312 unsigned long flags; 313 int rc; 314 315 rc = vbox_crtc_set_base(crtc, CRTC_FB(crtc), fb, 0, 0); 316 if (rc) 317 return rc; 318 319 mutex_lock(&vbox->hw_mutex); 320 vbox_do_modeset(crtc, &crtc->mode); 321 mutex_unlock(&vbox->hw_mutex); 322 323 spin_lock_irqsave(&drm->event_lock, flags); 324 325 if (event) 326 326 #if RTLNX_VER_MIN(3,19,0) || RTLNX_RHEL_MAJ_PREREQ(7,2) 327 328 #else 329 330 #endif 331 332 333 334 327 drm_crtc_send_vblank_event(crtc, event); 328 #else 329 drm_send_vblank_event(drm, -1, event); 330 #endif 331 332 spin_unlock_irqrestore(&drm->event_lock, flags); 333 334 return 0; 335 335 } 336 336 … … 348 348 349 349 static const struct drm_crtc_helper_funcs vbox_crtc_helper_funcs = { 350 351 352 353 354 355 350 .dpms = vbox_crtc_dpms, 351 .mode_fixup = vbox_crtc_mode_fixup, 352 .mode_set = vbox_crtc_mode_set, 353 .disable = vbox_crtc_disable, 354 .prepare = vbox_crtc_prepare, 355 .commit = vbox_crtc_commit, 356 356 }; 357 357 … … 362 362 static void vbox_crtc_destroy(struct drm_crtc *crtc) 363 363 { 364 365 364 drm_crtc_cleanup(crtc); 365 kfree(crtc); 366 366 } 367 367 368 368 static const struct drm_crtc_funcs vbox_crtc_funcs = { 369 370 371 372 373 374 375 369 .cursor_move = vbox_cursor_move, 370 .cursor_set2 = vbox_cursor_set2, 371 .reset = vbox_crtc_reset, 372 .set_config = drm_crtc_helper_set_config, 373 /* .gamma_set = vbox_crtc_gamma_set, */ 374 .page_flip = vbox_crtc_page_flip, 375 .destroy = vbox_crtc_destroy, 376 376 }; 377 377 378 378 static struct vbox_crtc *vbox_crtc_init(struct drm_device *dev, unsigned int i) 379 379 { 380 381 382 383 384 385 386 387 388 389 390 391 392 380 struct vbox_crtc *vbox_crtc; 381 382 vbox_crtc = kzalloc(sizeof(*vbox_crtc), GFP_KERNEL); 383 if (!vbox_crtc) 384 return NULL; 385 386 vbox_crtc->crtc_id = i; 387 388 drm_crtc_init(dev, &vbox_crtc->base, &vbox_crtc_funcs); 389 drm_mode_crtc_set_gamma_size(&vbox_crtc->base, 256); 390 drm_crtc_helper_add(&vbox_crtc->base, &vbox_crtc_helper_funcs); 391 392 return vbox_crtc; 393 393 } 394 394 395 395 static void vbox_encoder_destroy(struct drm_encoder *encoder) 396 396 { 397 398 397 drm_encoder_cleanup(encoder); 398 kfree(encoder); 399 399 } 400 400 … … 402 402 static struct drm_encoder *drm_encoder_find(struct drm_device *dev, u32 id) 403 403 { 404 405 406 407 404 struct drm_mode_object *mo; 405 406 mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER); 407 return mo ? obj_to_encoder(mo) : NULL; 408 408 } 409 409 #endif 410 410 411 411 static struct drm_encoder *vbox_best_single_encoder(struct drm_connector 412 412 *connector) 413 413 { 414 414 #if RTLNX_VER_MIN(5,5,0) || RTLNX_RHEL_MIN(8,3) || RTLNX_SUSE_MAJ_PREREQ(15,3) … … 419 419 return encoder; 420 420 #else /* < 5.5 || RHEL < 8.3 */ 421 422 423 424 421 int enc_id = connector->encoder_ids[0]; 422 423 /* pick the encoder ids */ 424 if (enc_id) 425 425 # if RTLNX_VER_MIN(4,15,0) || RTLNX_RHEL_MAJ_PREREQ(7,6) || (defined(CONFIG_SUSE_VERSION) && RTLNX_VER_MIN(4,12,0)) 426 426 return drm_encoder_find(connector->dev, NULL, enc_id); 427 427 # else 428 428 return drm_encoder_find(connector->dev, enc_id); 429 429 # endif 430 430 #endif /* < 5.5 || RHEL < 8.3 */ 431 431 return NULL; 432 432 } 433 433 434 434 static const struct drm_encoder_funcs vbox_enc_funcs = { 435 435 .destroy = vbox_encoder_destroy, 436 436 }; 437 437 … … 441 441 442 442 static bool vbox_mode_fixup(struct drm_encoder *encoder, 443 444 445 { 446 443 const struct drm_display_mode *mode, 444 struct drm_display_mode *adjusted_mode) 445 { 446 return true; 447 447 } 448 448 449 449 static void vbox_encoder_mode_set(struct drm_encoder *encoder, 450 451 450 struct drm_display_mode *mode, 451 struct drm_display_mode *adjusted_mode) 452 452 { 453 453 } … … 462 462 463 463 static const struct drm_encoder_helper_funcs vbox_enc_helper_funcs = { 464 465 466 467 468 464 .dpms = vbox_encoder_dpms, 465 .mode_fixup = vbox_mode_fixup, 466 .prepare = vbox_encoder_prepare, 467 .commit = vbox_encoder_commit, 468 .mode_set = vbox_encoder_mode_set, 469 469 }; 470 470 471 471 static struct drm_encoder *vbox_encoder_init(struct drm_device *dev, 472 473 { 474 475 476 477 478 479 480 472 unsigned int i) 473 { 474 struct vbox_encoder *vbox_encoder; 475 476 vbox_encoder = kzalloc(sizeof(*vbox_encoder), GFP_KERNEL); 477 if (!vbox_encoder) 478 return NULL; 479 480 drm_encoder_init(dev, &vbox_encoder->base, &vbox_enc_funcs, 481 481 #if RTLNX_VER_MIN(4,5,0) || RTLNX_RHEL_MAJ_PREREQ(7,3) 482 483 #else 484 485 #endif 486 487 488 489 482 DRM_MODE_ENCODER_DAC, NULL); 483 #else 484 DRM_MODE_ENCODER_DAC); 485 #endif 486 drm_encoder_helper_add(&vbox_encoder->base, &vbox_enc_helper_funcs); 487 488 vbox_encoder->base.possible_crtcs = 1 << i; 489 return &vbox_encoder->base; 490 490 } 491 491 … … 497 497 */ 498 498 static void vbox_set_edid(struct drm_connector *connector, int width, 499 500 { 501 502 503 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,/* header */504 0x58, 0x58,/* manufacturer (VBX) */505 0x00, 0x00,/* product code */506 0x00, 0x00, 0x00, 0x00,/* serial number goes here */507 0x01,/* week of manufacture */508 0x00,/* year of manufacture */509 0x01, 0x03,/* EDID version */510 0x80,/* capabilities - digital */511 0x00,/* horiz. res in cm, zero for projectors */512 0x00,/* vert. res in cm */513 0x78,/* display gamma (120 == 2.2). */514 0xEE,/* features (standby, suspend, off, RGB, std */515 516 517 518 0x00, 0x00, 0x00,/* no default timings */519 520 521 0x01, 0x01, 0x01, 0x01,/* no standard timings */522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 0x00,/* number of extensions */542 0x00/* checksum goes here */543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 499 int height) 500 { 501 enum { EDID_SIZE = 128 }; 502 unsigned char edid[EDID_SIZE] = { 503 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, /* header */ 504 0x58, 0x58, /* manufacturer (VBX) */ 505 0x00, 0x00, /* product code */ 506 0x00, 0x00, 0x00, 0x00, /* serial number goes here */ 507 0x01, /* week of manufacture */ 508 0x00, /* year of manufacture */ 509 0x01, 0x03, /* EDID version */ 510 0x80, /* capabilities - digital */ 511 0x00, /* horiz. res in cm, zero for projectors */ 512 0x00, /* vert. res in cm */ 513 0x78, /* display gamma (120 == 2.2). */ 514 0xEE, /* features (standby, suspend, off, RGB, std */ 515 /* colour space, preferred timing mode) */ 516 0xEE, 0x91, 0xA3, 0x54, 0x4C, 0x99, 0x26, 0x0F, 0x50, 0x54, 517 /* chromaticity for standard colour space. */ 518 0x00, 0x00, 0x00, /* no default timings */ 519 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 520 0x01, 0x01, 521 0x01, 0x01, 0x01, 0x01, /* no standard timings */ 522 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x02, 0x02, 523 0x02, 0x02, 524 /* descriptor block 1 goes below */ 525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 526 /* descriptor block 2, monitor ranges */ 527 0x00, 0x00, 0x00, 0xFD, 0x00, 528 0x00, 0xC8, 0x00, 0xC8, 0x64, 0x00, 0x0A, 0x20, 0x20, 0x20, 529 0x20, 0x20, 530 /* 0-200Hz vertical, 0-200KHz horizontal, 1000MHz pixel clock */ 531 0x20, 532 /* descriptor block 3, monitor name */ 533 0x00, 0x00, 0x00, 0xFC, 0x00, 534 'V', 'B', 'O', 'X', ' ', 'm', 'o', 'n', 'i', 't', 'o', 'r', 535 '\n', 536 /* descriptor block 4: dummy data */ 537 0x00, 0x00, 0x00, 0x10, 0x00, 538 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 539 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 540 0x20, 541 0x00, /* number of extensions */ 542 0x00 /* checksum goes here */ 543 }; 544 int clock = (width + 6) * (height + 6) * 60 / 10000; 545 unsigned int i, sum = 0; 546 547 edid[12] = width & 0xff; 548 edid[13] = width >> 8; 549 edid[14] = height & 0xff; 550 edid[15] = height >> 8; 551 edid[54] = clock & 0xff; 552 edid[55] = clock >> 8; 553 edid[56] = width & 0xff; 554 edid[58] = (width >> 4) & 0xf0; 555 edid[59] = height & 0xff; 556 edid[61] = (height >> 4) & 0xf0; 557 for (i = 0; i < EDID_SIZE - 1; ++i) 558 sum += edid[i]; 559 edid[EDID_SIZE - 1] = (0x100 - (sum & 0xFF)) & 0xFF; 560 560 #if RTLNX_VER_MIN(4,19,0) || RTLNX_RHEL_MAJ_PREREQ(7,7) || RTLNX_RHEL_MAJ_PREREQ(8,1) || RTLNX_SUSE_MAJ_PREREQ(15,1) || RTLNX_SUSE_MAJ_PREREQ(12,5) 561 562 #else 563 561 drm_connector_update_edid_property(connector, (struct edid *)edid); 562 #else 563 drm_mode_connector_update_edid_property(connector, (struct edid *)edid); 564 564 #endif 565 565 } … … 567 567 static int vbox_get_modes(struct drm_connector *connector) 568 568 { 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 569 struct vbox_connector *vbox_connector = NULL; 570 struct drm_display_mode *mode = NULL; 571 struct vbox_private *vbox = NULL; 572 unsigned int num_modes = 0; 573 int preferred_width, preferred_height; 574 575 vbox_connector = to_vbox_connector(connector); 576 vbox = connector->dev->dev_private; 577 /* 578 * Heuristic: we do not want to tell the host that we support dynamic 579 * resizing unless we feel confident that the user space client using 580 * the video driver can handle hot-plug events. So the first time modes 581 * are queried after a "master" switch we tell the host that we do not, 582 * and immediately after we send the client a hot-plug notification as 583 * a test to see if they will respond and query again. 584 * That is also the reason why capabilities are reported to the host at 585 * this place in the code rather than elsewhere. 586 * We need to report the flags location before reporting the IRQ 587 * capability. 588 */ 589 VBoxHGSMIReportFlagsLocation(vbox->guest_pool, GUEST_HEAP_OFFSET(vbox) + 590 HOST_FLAGS_OFFSET); 591 if (vbox_connector->vbox_crtc->crtc_id == 0) 592 vbox_report_caps(vbox); 593 if (!vbox->initial_mode_queried) { 594 if (vbox_connector->vbox_crtc->crtc_id == 0) { 595 vbox->initial_mode_queried = true; 596 vbox_report_hotplug(vbox); 597 } 598 return drm_add_modes_noedid(connector, 800, 600); 599 } 600 /* Also assume that a client which supports hot-plugging also knows 601 * how to update the screen in a way we can use, the only known 602 * relevent client which cannot is Plymouth in Ubuntu 14.04. */ 603 vbox->need_refresh_timer = false; 604 num_modes = drm_add_modes_noedid(connector, 2560, 1600); 605 preferred_width = vbox_connector->mode_hint.width ? 606 vbox_connector->mode_hint.width : 1024; 607 preferred_height = vbox_connector->mode_hint.height ? 608 vbox_connector->mode_hint.height : 768; 609 mode = drm_cvt_mode(connector->dev, preferred_width, preferred_height, 610 60, false, false, false); 611 if (mode) { 612 mode->type |= DRM_MODE_TYPE_PREFERRED; 613 drm_mode_probed_add(connector, mode); 614 ++num_modes; 615 } 616 vbox_set_edid(connector, preferred_width, preferred_height); 617 617 618 618 #if RTLNX_VER_MIN(3,19,0) || RTLNX_RHEL_MAJ_PREREQ(7,2) 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 #endif 635 636 619 if (vbox_connector->vbox_crtc->x_hint != -1) 620 drm_object_property_set_value(&connector->base, 621 vbox->dev->mode_config.suggested_x_property, 622 vbox_connector->vbox_crtc->x_hint); 623 else 624 drm_object_property_set_value(&connector->base, 625 vbox->dev->mode_config.suggested_x_property, 0); 626 627 if (vbox_connector->vbox_crtc->y_hint != -1) 628 drm_object_property_set_value(&connector->base, 629 vbox->dev->mode_config.suggested_y_property, 630 vbox_connector->vbox_crtc->y_hint); 631 else 632 drm_object_property_set_value(&connector->base, 633 vbox->dev->mode_config.suggested_y_property, 0); 634 #endif 635 636 return num_modes; 637 637 } 638 638 … … 642 642 static enum drm_mode_status vbox_mode_valid(struct drm_connector *connector, 643 643 #endif 644 645 { 646 644 struct drm_display_mode *mode) 645 { 646 return MODE_OK; 647 647 } 648 648 … … 650 650 { 651 651 #if RTLNX_VER_MAX(3,17,0) && !RTLNX_RHEL_MAJ_PREREQ(7,2) 652 653 #else 654 655 #endif 656 657 652 drm_sysfs_connector_remove(connector); 653 #else 654 drm_connector_unregister(connector); 655 #endif 656 drm_connector_cleanup(connector); 657 kfree(connector); 658 658 } 659 659 … … 661 661 vbox_connector_detect(struct drm_connector *connector, bool force) 662 662 { 663 664 665 666 667 668 663 struct vbox_connector *vbox_connector; 664 665 vbox_connector = to_vbox_connector(connector); 666 667 return vbox_connector->mode_hint.disconnected ? 668 connector_status_disconnected : connector_status_connected; 669 669 } 670 670 671 671 static int vbox_fill_modes(struct drm_connector *connector, u32 max_x, 672 673 { 674 675 676 677 678 679 680 681 682 683 684 685 672 u32 max_y) 673 { 674 struct vbox_connector *vbox_connector; 675 struct drm_device *dev; 676 struct drm_display_mode *mode, *iterator; 677 678 vbox_connector = to_vbox_connector(connector); 679 dev = vbox_connector->base.dev; 680 list_for_each_entry_safe(mode, iterator, &connector->modes, head) { 681 list_del(&mode->head); 682 drm_mode_destroy(dev, mode); 683 } 684 685 return drm_helper_probe_single_connector_modes(connector, max_x, max_y); 686 686 } 687 687 688 688 static const struct drm_connector_helper_funcs vbox_connector_helper_funcs = { 689 690 691 689 .mode_valid = vbox_mode_valid, 690 .get_modes = vbox_get_modes, 691 .best_encoder = vbox_best_single_encoder, 692 692 }; 693 693 694 694 static const struct drm_connector_funcs vbox_connector_funcs = { 695 696 697 698 695 .dpms = drm_helper_connector_dpms, 696 .detect = vbox_connector_detect, 697 .fill_modes = vbox_fill_modes, 698 .destroy = vbox_connector_destroy, 699 699 }; 700 700 701 701 static int vbox_connector_init(struct drm_device *dev, 702 703 704 { 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 702 struct vbox_crtc *vbox_crtc, 703 struct drm_encoder *encoder) 704 { 705 struct vbox_connector *vbox_connector; 706 struct drm_connector *connector; 707 708 vbox_connector = kzalloc(sizeof(*vbox_connector), GFP_KERNEL); 709 if (!vbox_connector) 710 return -ENOMEM; 711 712 connector = &vbox_connector->base; 713 vbox_connector->vbox_crtc = vbox_crtc; 714 715 drm_connector_init(dev, connector, &vbox_connector_funcs, 716 DRM_MODE_CONNECTOR_VGA); 717 drm_connector_helper_add(connector, &vbox_connector_helper_funcs); 718 719 connector->interlace_allowed = 0; 720 connector->doublescan_allowed = 0; 721 721 722 722 #if RTLNX_VER_MIN(3,19,0) || RTLNX_RHEL_MAJ_PREREQ(7,2) 723 724 725 726 727 723 drm_mode_create_suggested_offset_properties(dev); 724 drm_object_attach_property(&connector->base, 725 dev->mode_config.suggested_x_property, 0); 726 drm_object_attach_property(&connector->base, 727 dev->mode_config.suggested_y_property, 0); 728 728 #endif 729 729 #if RTLNX_VER_MAX(3,17,0) && !RTLNX_RHEL_MAJ_PREREQ(7,2) 730 731 #else 732 730 drm_sysfs_connector_add(connector); 731 #else 732 drm_connector_register(connector); 733 733 #endif 734 734 735 735 #if RTLNX_VER_MIN(4,19,0) || RTLNX_RHEL_MAJ_PREREQ(7,7) || RTLNX_RHEL_MAJ_PREREQ(8,1) || RTLNX_SUSE_MAJ_PREREQ(15,1) || RTLNX_SUSE_MAJ_PREREQ(12,5) 736 737 #else 738 739 #endif 740 741 736 drm_connector_attach_encoder(connector, encoder); 737 #else 738 drm_mode_connector_attach_encoder(connector, encoder); 739 #endif 740 741 return 0; 742 742 } 743 743 744 744 int vbox_mode_init(struct drm_device *dev) 745 745 { 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 746 struct vbox_private *vbox = dev->dev_private; 747 struct drm_encoder *encoder; 748 struct vbox_crtc *vbox_crtc; 749 unsigned int i; 750 int ret; 751 752 /* vbox_cursor_init(dev); */ 753 for (i = 0; i < vbox->num_crtcs; ++i) { 754 vbox_crtc = vbox_crtc_init(dev, i); 755 if (!vbox_crtc) 756 return -ENOMEM; 757 encoder = vbox_encoder_init(dev, i); 758 if (!encoder) 759 return -ENOMEM; 760 ret = vbox_connector_init(dev, vbox_crtc, encoder); 761 if (ret) 762 return ret; 763 } 764 765 return 0; 766 766 } 767 767 768 768 void vbox_mode_fini(struct drm_device *dev) 769 769 { 770 770 /* vbox_cursor_fini(dev); */ 771 771 } 772 772 … … 777 777 */ 778 778 static void copy_cursor_image(u8 *src, u8 *dst, u32 width, u32 height, 779 780 { 781 782 783 784 785 786 787 788 779 size_t mask_size) 780 { 781 size_t line_size = (width + 7) / 8; 782 u32 i, j; 783 784 memcpy(dst + mask_size, src, width * height * 4); 785 for (i = 0; i < height; ++i) 786 for (j = 0; j < width; ++j) 787 if (((u32 *)src)[i * width + j] > 0xf0000000) 788 dst[i * line_size + j / 8] |= (0x80 >> (j % 8)); 789 789 } 790 790 791 791 static int vbox_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv, 792 793 794 { 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 792 u32 handle, u32 width, u32 height, 793 s32 hot_x, s32 hot_y) 794 { 795 struct vbox_private *vbox = crtc->dev->dev_private; 796 struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc); 797 struct ttm_bo_kmap_obj uobj_map; 798 size_t data_size, mask_size; 799 struct drm_gem_object *obj; 800 u32 flags, caps = 0; 801 struct vbox_bo *bo; 802 bool src_isiomem; 803 u8 *dst = NULL; 804 u8 *src; 805 int ret; 806 807 if (!handle) { 808 bool cursor_enabled = false; 809 struct drm_crtc *crtci; 810 811 /* Hide cursor. */ 812 vbox_crtc->cursor_enabled = false; 813 list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list, 814 head) { 815 if (to_vbox_crtc(crtci)->cursor_enabled) 816 cursor_enabled = true; 817 } 818 819 if (!cursor_enabled) 820 VBoxHGSMIUpdatePointerShape(vbox->guest_pool, 0, 0, 0, 821 0, 0, NULL, 0); 822 return 0; 823 } 824 825 vbox_crtc->cursor_enabled = true; 826 827 if (width > VBOX_MAX_CURSOR_WIDTH || height > VBOX_MAX_CURSOR_HEIGHT || 828 width == 0 || height == 0) 829 return -EINVAL; 830 ret = VBoxQueryConfHGSMI(vbox->guest_pool, 831 VBOX_VBVA_CONF32_CURSOR_CAPABILITIES, &caps); 832 if (ret) 833 return ret == VERR_NO_MEMORY ? -ENOMEM : -EINVAL; 834 835 if (!(caps & VBOX_VBVA_CURSOR_CAPABILITY_HARDWARE)) { 836 /* 837 * -EINVAL means cursor_set2() not supported, -EAGAIN means 838 * retry at once. 839 */ 840 return -EBUSY; 841 } 842 842 843 843 #if RTLNX_VER_MIN(4,7,0) || RTLNX_RHEL_MAJ_PREREQ(7,4) 844 845 #else 846 847 #endif 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 844 obj = drm_gem_object_lookup(file_priv, handle); 845 #else 846 obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); 847 #endif 848 if (!obj) { 849 DRM_ERROR("Cannot find cursor object %x for crtc\n", handle); 850 return -ENOENT; 851 } 852 853 bo = gem_to_vbox_bo(obj); 854 ret = vbox_bo_reserve(bo, false); 855 if (ret) 856 goto out_unref_obj; 857 858 /* 859 * The mask must be calculated based on the alpha 860 * channel, one bit per ARGB word, and must be 32-bit 861 * padded. 862 */ 863 mask_size = ((width + 7) / 8 * height + 3) & ~3; 864 data_size = width * height * 4 + mask_size; 865 vbox->cursor_hot_x = hot_x; 866 vbox->cursor_hot_y = hot_y; 867 vbox->cursor_width = width; 868 vbox->cursor_height = height; 869 vbox->cursor_data_size = data_size; 870 dst = vbox->cursor_data; 871 871 872 872 #if RTLNX_VER_MIN(6,4,0) 873 874 875 876 877 878 879 873 /* Make sure bo is in SYSTEM (main) memory, so we can access it directly. */ 874 ret = vbox_bo_pin(bo, VBOX_MEM_TYPE_SYSTEM, NULL); 875 if (ret) 876 { 877 DRM_ERROR("cannot pin bo to main memory\n"); 878 goto out_bo_unpin; 879 } 880 880 #endif 881 881 882 882 #if RTLNX_VER_MIN(5,14,0) || RTLNX_RHEL_RANGE(8,6, 8,99) 883 883 ret = ttm_bo_kmap(&bo->bo, 0, VBOX_BO_RESOURCE_NUM_PAGES(bo->bo.resource), &uobj_map); 884 884 #elif RTLNX_VER_MIN(5,12,0) || RTLNX_RHEL_MAJ_PREREQ(8,5) 885 886 #else 887 888 #endif 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 885 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.mem.num_pages, &uobj_map); 886 #else 887 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &uobj_map); 888 #endif 889 if (ret) { 890 vbox->cursor_data_size = 0; 891 goto out_unreserve_bo; 892 } 893 894 src = ttm_kmap_obj_virtual(&uobj_map, &src_isiomem); 895 if (src_isiomem) { 896 DRM_ERROR("src cursor bo not in main memory\n"); 897 ret = -EIO; 898 goto out_unmap_bo; 899 } 900 901 copy_cursor_image(src, dst, width, height, mask_size); 902 903 flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE | 904 VBOX_MOUSE_POINTER_ALPHA; 905 ret = VBoxHGSMIUpdatePointerShape(vbox->guest_pool, flags, 906 vbox->cursor_hot_x, vbox->cursor_hot_y, 907 width, height, dst, data_size); 908 ret = ret == VINF_SUCCESS ? 0 : ret == VERR_NO_MEMORY ? -ENOMEM : 909 ret == VERR_NOT_SUPPORTED ? -EBUSY : -EINVAL; 910 910 911 911 out_unmap_bo: 912 912 ttm_bo_kunmap(&uobj_map); 913 913 #if RTLNX_VER_MIN(6,4,0) 914 914 out_bo_unpin: 915 915 vbox_bo_unpin(bo); 916 916 #endif 917 917 out_unreserve_bo: 918 918 vbox_bo_unreserve(bo); 919 919 out_unref_obj: 920 920 #if RTLNX_VER_MIN(5,9,0) || RTLNX_RHEL_MIN(8,4) || RTLNX_SUSE_MAJ_PREREQ(15,3) 921 922 #else 923 924 #endif 925 926 921 drm_gem_object_put(obj); 922 #else 923 drm_gem_object_put_unlocked(obj); 924 #endif 925 926 return ret; 927 927 } 928 928 929 929 static int vbox_cursor_move(struct drm_crtc *crtc, int x, int y) 930 930 { 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 ret = VBoxHGSMICursorPosition(vbox->guest_pool, true, x + crtc_x,946 947 948 949 } 931 struct vbox_private *vbox = crtc->dev->dev_private; 932 s32 crtc_x = 933 vbox->single_framebuffer ? crtc->x : to_vbox_crtc(crtc)->x_hint; 934 s32 crtc_y = 935 vbox->single_framebuffer ? crtc->y : to_vbox_crtc(crtc)->y_hint; 936 int ret; 937 938 x += vbox->cursor_hot_x; 939 y += vbox->cursor_hot_y; 940 if (x + crtc_x < 0 || y + crtc_y < 0 || 941 x + crtc_x >= vbox->input_mapping_width || 942 y + crtc_y >= vbox->input_mapping_width || 943 vbox->cursor_data_size == 0) 944 return 0; 945 ret = VBoxHGSMIReportCursorPosition(vbox->guest_pool, true, x + crtc_x, 946 y + crtc_y, NULL, NULL); 947 return ret == VINF_SUCCESS ? 0 : ret == VERR_NO_MEMORY ? -ENOMEM : ret == 948 VERR_NOT_SUPPORTED ? -EBUSY : -EINVAL; 949 } -
trunk/src/VBox/Additions/x11/vboxvideo/pointer.c
r98103 r104834 192 192 VBOXPtr pVBox = pScrn->driverPrivate; 193 193 194 /* This currently does nothing. */ 195 VBoxHGSMICursorPosition(&pVBox->guestCtx, true, x, y, NULL, NULL); 194 VBoxHGSMIReportCursorPosition(&pVBox->guestCtx, true, x, y, NULL, NULL); 196 195 } 197 196
Note:
See TracChangeset
for help on using the changeset viewer.