Changeset View
Changeset View
Standalone View
Standalone View
src/server/surface_interface.cpp
Show First 20 Lines • Show All 268 Lines • ▼ Show 20 Line(s) | 268 | const struct wl_surface_interface SurfaceInterface::Private::s_interface = { | |||
---|---|---|---|---|---|
269 | resourceDestroyedCallback, | 269 | resourceDestroyedCallback, | ||
270 | attachCallback, | 270 | attachCallback, | ||
271 | damageCallback, | 271 | damageCallback, | ||
272 | frameCallback, | 272 | frameCallback, | ||
273 | opaqueRegionCallback, | 273 | opaqueRegionCallback, | ||
274 | inputRegionCallback, | 274 | inputRegionCallback, | ||
275 | commitCallback, | 275 | commitCallback, | ||
276 | bufferTransformCallback, | 276 | bufferTransformCallback, | ||
277 | bufferScaleCallback | 277 | bufferScaleCallback, | ||
278 | damageBufferCallback | ||||
278 | }; | 279 | }; | ||
279 | #endif | 280 | #endif | ||
280 | 281 | | |||
281 | SurfaceInterface::SurfaceInterface(CompositorInterface *parent, wl_resource *parentResource) | 282 | SurfaceInterface::SurfaceInterface(CompositorInterface *parent, wl_resource *parentResource) | ||
282 | : Resource(new Private(this, parent, parentResource)) | 283 | : Resource(new Private(this, parent, parentResource)) | ||
283 | { | 284 | { | ||
284 | } | 285 | } | ||
285 | 286 | | |||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Line(s) | 367 | if (!target->buffer && !source->buffer && emitChanged) { | |||
368 | bufferChanged = false; | 369 | bufferChanged = false; | ||
369 | } | 370 | } | ||
370 | buffer = source->buffer; | 371 | buffer = source->buffer; | ||
371 | } | 372 | } | ||
372 | // copy values | 373 | // copy values | ||
373 | if (bufferChanged) { | 374 | if (bufferChanged) { | ||
374 | target->buffer = buffer; | 375 | target->buffer = buffer; | ||
375 | target->damage = source->damage; | 376 | target->damage = source->damage; | ||
377 | target->bufferDamage = source->bufferDamage; | ||||
376 | target->bufferIsSet = source->bufferIsSet; | 378 | target->bufferIsSet = source->bufferIsSet; | ||
377 | } | 379 | } | ||
378 | if (childrenChanged) { | 380 | if (childrenChanged) { | ||
379 | target->childrenChanged = source->childrenChanged; | 381 | target->childrenChanged = source->childrenChanged; | ||
380 | target->children = source->children; | 382 | target->children = source->children; | ||
381 | } | 383 | } | ||
382 | target->callbacks.append(source->callbacks); | 384 | target->callbacks.append(source->callbacks); | ||
383 | 385 | | |||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Line(s) | 434 | if (scaleFactorChanged) { | |||
434 | if (buffer && !sizeChanged) { | 436 | if (buffer && !sizeChanged) { | ||
435 | emit q->sizeChanged(); | 437 | emit q->sizeChanged(); | ||
436 | } | 438 | } | ||
437 | } | 439 | } | ||
438 | if (transformChanged) { | 440 | if (transformChanged) { | ||
439 | emit q->transformChanged(target->transform); | 441 | emit q->transformChanged(target->transform); | ||
440 | } | 442 | } | ||
441 | if (bufferChanged && emitChanged) { | 443 | if (bufferChanged && emitChanged) { | ||
442 | if (target->buffer && !target->damage.isEmpty()) { | 444 | if (target->buffer && (!target->damage.isEmpty() || !target->bufferDamage.isEmpty())) { | ||
443 | const QRegion windowRegion = QRegion(0, 0, q->size().width(), q->size().height()); | 445 | const QRegion windowRegion = QRegion(0, 0, q->size().width(), q->size().height()); | ||
444 | if (!windowRegion.isEmpty()) { | 446 | if (!windowRegion.isEmpty()) { | ||
445 | target->damage = windowRegion.intersected(target->damage); | 447 | QRegion bufferDamage; | ||
448 | if (!target->bufferDamage.isEmpty()) { | ||||
449 | typedef OutputInterface::Transform Tr; | ||||
450 | const Tr tr = target->transform; | ||||
davidedmundson: scale is also a transform.
Note also that the damage signal is used in kwin assuming it's… | |||||
Thanks! After applying the output transform and the scale transform, the damaged buffer region should be in surface local coordinates, right? I.e. the below sent damaged signal should then have the surface local damage. romangg: Thanks! After applying the output transform **and** the scale transform, the damaged buffer… | |||||
451 | const qint32 sc = target->scale; | ||||
452 | if (tr == Tr::Rotated90 || tr == Tr::Rotated270 || | ||||
453 | tr == Tr::Flipped90 || tr == Tr::Flipped270) { | ||||
davidedmundson: Should this last one be flipped 270? | |||||
454 | // calculate transformed + scaled buffer damage | ||||
455 | for (const auto &rect : target->bufferDamage) { | ||||
456 | const auto add = QRegion(rect.x() / sc, rect.y() / sc, rect.height() / sc, rect.width() / sc); | ||||
457 | bufferDamage = bufferDamage.united(add); | ||||
458 | } | ||||
459 | } else if (sc != 1) { | ||||
460 | // calculate scaled buffer damage | ||||
461 | for (const auto &rect : target->bufferDamage) { | ||||
462 | const auto add = QRegion(rect.x() / sc, rect.y() / sc, rect.width() / sc, rect.height() / sc); | ||||
463 | bufferDamage = bufferDamage.united(add); | ||||
464 | } | ||||
465 | } else { | ||||
466 | bufferDamage = target->bufferDamage; | ||||
467 | } | ||||
468 | } | ||||
469 | target->damage = windowRegion.intersected(target->damage.united(bufferDamage)); | ||||
446 | if (emitChanged) { | 470 | if (emitChanged) { | ||
447 | subSurfaceIsMapped = true; | 471 | subSurfaceIsMapped = true; | ||
448 | trackedDamage = trackedDamage.united(target->damage); | 472 | trackedDamage = trackedDamage.united(target->damage); | ||
449 | emit q->damaged(target->damage); | 473 | emit q->damaged(target->damage); | ||
450 | // workaround for https://bugreports.qt.io/browse/QTBUG-52092 | 474 | // workaround for https://bugreports.qt.io/browse/QTBUG-52092 | ||
451 | // if the surface is a sub-surface, but the main surface is not yet mapped, fake frame rendered | 475 | // if the surface is a sub-surface, but the main surface is not yet mapped, fake frame rendered | ||
452 | if (subSurface) { | 476 | if (subSurface) { | ||
453 | const auto mainSurface = subSurface->mainSurface(); | 477 | const auto mainSurface = subSurface->mainSurface(); | ||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Line(s) | 534 | { | |||
522 | } | 546 | } | ||
523 | } | 547 | } | ||
524 | 548 | | |||
525 | void SurfaceInterface::Private::damage(const QRect &rect) | 549 | void SurfaceInterface::Private::damage(const QRect &rect) | ||
526 | { | 550 | { | ||
527 | pending.damage = pending.damage.united(rect); | 551 | pending.damage = pending.damage.united(rect); | ||
528 | } | 552 | } | ||
529 | 553 | | |||
554 | void SurfaceInterface::Private::damageBuffer(const QRect &rect) | ||||
555 | { | ||||
556 | if (!pending.bufferIsSet || (pending.bufferIsSet && !pending.buffer)) { | ||||
557 | // TODO: should we send an error? | ||||
558 | return; | ||||
559 | } | ||||
560 | pending.bufferDamage = pending.bufferDamage.united(rect); | ||||
561 | } | ||||
562 | | ||||
530 | void SurfaceInterface::Private::setScale(qint32 scale) | 563 | void SurfaceInterface::Private::setScale(qint32 scale) | ||
531 | { | 564 | { | ||
532 | pending.scale = scale; | 565 | pending.scale = scale; | ||
533 | pending.scaleIsSet = true; | 566 | pending.scaleIsSet = true; | ||
534 | } | 567 | } | ||
535 | 568 | | |||
536 | void SurfaceInterface::Private::setTransform(OutputInterface::Transform transform) | 569 | void SurfaceInterface::Private::setTransform(OutputInterface::Transform transform) | ||
537 | { | 570 | { | ||
Show All 17 Lines | 586 | { | |||
555 | pending.offset = offset; | 588 | pending.offset = offset; | ||
556 | if (pending.buffer) { | 589 | if (pending.buffer) { | ||
557 | delete pending.buffer; | 590 | delete pending.buffer; | ||
558 | } | 591 | } | ||
559 | if (!buffer) { | 592 | if (!buffer) { | ||
560 | // got a null buffer, deletes content in next frame | 593 | // got a null buffer, deletes content in next frame | ||
561 | pending.buffer = nullptr; | 594 | pending.buffer = nullptr; | ||
562 | pending.damage = QRegion(); | 595 | pending.damage = QRegion(); | ||
596 | pending.bufferDamage = QRegion(); | ||||
563 | return; | 597 | return; | ||
564 | } | 598 | } | ||
565 | Q_Q(SurfaceInterface); | 599 | Q_Q(SurfaceInterface); | ||
566 | pending.buffer = new BufferInterface(buffer, q); | 600 | pending.buffer = new BufferInterface(buffer, q); | ||
567 | QObject::connect(pending.buffer, &BufferInterface::aboutToBeDestroyed, q, | 601 | QObject::connect(pending.buffer, &BufferInterface::aboutToBeDestroyed, q, | ||
568 | [this](BufferInterface *buffer) { | 602 | [this](BufferInterface *buffer) { | ||
569 | if (pending.buffer == buffer) { | 603 | if (pending.buffer == buffer) { | ||
570 | pending.buffer = nullptr; | 604 | pending.buffer = nullptr; | ||
Show All 24 Lines | |||||
595 | } | 629 | } | ||
596 | 630 | | |||
597 | void SurfaceInterface::Private::damageCallback(wl_client *client, wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) | 631 | void SurfaceInterface::Private::damageCallback(wl_client *client, wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) | ||
598 | { | 632 | { | ||
599 | Q_UNUSED(client) | 633 | Q_UNUSED(client) | ||
600 | cast<Private>(resource)->damage(QRect(x, y, width, height)); | 634 | cast<Private>(resource)->damage(QRect(x, y, width, height)); | ||
601 | } | 635 | } | ||
602 | 636 | | |||
637 | void SurfaceInterface::Private::damageBufferCallback(wl_client *client, wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) | ||||
638 | { | ||||
639 | Q_UNUSED(client) | ||||
640 | cast<Private>(resource)->damageBuffer(QRect(x, y, width, height)); | ||||
641 | } | ||||
642 | | ||||
603 | void SurfaceInterface::Private::frameCallback(wl_client *client, wl_resource *resource, uint32_t callback) | 643 | void SurfaceInterface::Private::frameCallback(wl_client *client, wl_resource *resource, uint32_t callback) | ||
604 | { | 644 | { | ||
605 | auto s = cast<Private>(resource); | 645 | auto s = cast<Private>(resource); | ||
606 | Q_ASSERT(client == *s->client); | 646 | Q_ASSERT(client == *s->client); | ||
607 | s->addFrameCallback(callback); | 647 | s->addFrameCallback(callback); | ||
608 | } | 648 | } | ||
609 | 649 | | |||
610 | void SurfaceInterface::Private::opaqueRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region) | 650 | void SurfaceInterface::Private::opaqueRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region) | ||
▲ Show 20 Lines • Show All 302 Lines • Show Last 20 Lines |
scale is also a transform.
Note also that the damage signal is used in kwin assuming it's surface local.