Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: cc/thread_proxy.cc

Issue 11362054: Use message passing for BeginFrameAndCommitState and clean up forced commit logic (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« cc/scheduler_state_machine.cc ('K') | « cc/thread_proxy.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 The Chromium Authors. All rights reserved. 1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 6
7 #include "cc/thread_proxy.h" 7 #include "cc/thread_proxy.h"
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 20 matching lines...) Expand all
31 31
32 scoped_ptr<Proxy> ThreadProxy::create(LayerTreeHost* layerTreeHost) 32 scoped_ptr<Proxy> ThreadProxy::create(LayerTreeHost* layerTreeHost)
33 { 33 {
34 return make_scoped_ptr(new ThreadProxy(layerTreeHost)).PassAs<Proxy>(); 34 return make_scoped_ptr(new ThreadProxy(layerTreeHost)).PassAs<Proxy>();
35 } 35 }
36 36
37 ThreadProxy::ThreadProxy(LayerTreeHost* layerTreeHost) 37 ThreadProxy::ThreadProxy(LayerTreeHost* layerTreeHost)
38 : m_animateRequested(false) 38 : m_animateRequested(false)
39 , m_commitRequested(false) 39 , m_commitRequested(false)
40 , m_commitRequestSentToImplThread(false) 40 , m_commitRequestSentToImplThread(false)
41 , m_forcedCommitRequested(false)
42 , m_layerTreeHost(layerTreeHost) 41 , m_layerTreeHost(layerTreeHost)
43 , m_rendererInitialized(false) 42 , m_rendererInitialized(false)
44 , m_started(false) 43 , m_started(false)
45 , m_texturesAcquired(true) 44 , m_texturesAcquired(true)
46 , m_inCompositeAndReadback(false) 45 , m_inCompositeAndReadback(false)
47 , m_mainThreadProxy(ScopedThreadProxy::create(Proxy::mainThread())) 46 , m_mainThreadProxy(ScopedThreadProxy::create(Proxy::mainThread()))
48 , m_beginFrameCompletionEventOnImplThread(0) 47 , m_beginFrameCompletionEventOnImplThread(0)
49 , m_readbackRequestOnImplThread(0) 48 , m_readbackRequestOnImplThread(0)
50 , m_commitCompletionEventOnImplThread(0) 49 , m_commitCompletionEventOnImplThread(0)
51 , m_textureAcquisitionCompletionEventOnImplThread(0) 50 , m_textureAcquisitionCompletionEventOnImplThread(0)
52 , m_nextFrameIsNewlyCommittedFrameOnImplThread(false) 51 , m_nextFrameIsNewlyCommittedFrameOnImplThread(false)
53 , m_renderVSyncEnabled(layerTreeHost->settings().renderVSyncEnabled) 52 , m_renderVSyncEnabled(layerTreeHost->settings().renderVSyncEnabled)
54 , m_totalCommitCount(0) 53 , m_totalCommitCount(0)
55 , m_deferCommits(false) 54 , m_deferCommits(false)
56 , m_deferredCommitPending(false)
57 { 55 {
58 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy"); 56 TRACE_EVENT0("cc", "ThreadProxy::ThreadProxy");
59 DCHECK(isMainThread()); 57 DCHECK(isMainThread());
60 } 58 }
61 59
62 ThreadProxy::~ThreadProxy() 60 ThreadProxy::~ThreadProxy()
63 { 61 {
64 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy"); 62 TRACE_EVENT0("cc", "ThreadProxy::~ThreadProxy");
65 DCHECK(isMainThread()); 63 DCHECK(isMainThread());
66 DCHECK(!m_started); 64 DCHECK(!m_started);
67 } 65 }
68 66
69 bool ThreadProxy::compositeAndReadback(void *pixels, const gfx::Rect& rect) 67 bool ThreadProxy::compositeAndReadback(void *pixels, const gfx::Rect& rect)
70 { 68 {
71 TRACE_EVENT0("cc", "ThreadPRoxy::compositeAndReadback"); 69 TRACE_EVENT0("cc", "ThreadProxy::compositeAndReadback");
72 DCHECK(isMainThread()); 70 DCHECK(isMainThread());
73 DCHECK(m_layerTreeHost); 71 DCHECK(m_layerTreeHost);
74 DCHECK(!m_deferCommits); 72 DCHECK(!m_deferCommits);
75 73
76 if (!m_layerTreeHost->initializeRendererIfNeeded()) { 74 if (!m_layerTreeHost->initializeRendererIfNeeded()) {
77 TRACE_EVENT0("cc", "compositeAndReadback_EarlyOut_LR_Uninitialized"); 75 TRACE_EVENT0("cc", "compositeAndReadback_EarlyOut_LR_Uninitialized");
78 return false; 76 return false;
79 } 77 }
80 78
81 79
82 // Perform a synchronous commit. 80 // Perform a synchronous commit.
83 { 81 {
84 DebugScopedSetMainThreadBlocked mainThreadBlocked; 82 DebugScopedSetMainThreadBlocked mainThreadBlocked;
85 CompletionEvent beginFrameCompletion; 83 CompletionEvent beginFrameCompletion;
86 Proxy::implThread()->postTask(base::Bind(&ThreadProxy::forceBeginFrameOn ImplThread, base::Unretained(this), &beginFrameCompletion)); 84 Proxy::implThread()->postTask(base::Bind(&ThreadProxy::forceBeginFrameOn ImplThread, base::Unretained(this), &beginFrameCompletion));
87 beginFrameCompletion.wait(); 85 beginFrameCompletion.wait();
88 } 86 }
89 m_inCompositeAndReadback = true; 87 m_inCompositeAndReadback = true;
90 beginFrame(); 88 beginFrame(scoped_ptr<BeginFrameAndCommitState>());
91 m_inCompositeAndReadback = false; 89 m_inCompositeAndReadback = false;
92 90
93 // Perform a synchronous readback. 91 // Perform a synchronous readback.
94 ReadbackRequest request; 92 ReadbackRequest request;
95 request.rect = rect; 93 request.rect = rect;
96 request.pixels = pixels; 94 request.pixels = pixels;
97 { 95 {
98 DebugScopedSetMainThreadBlocked mainThreadBlocked; 96 DebugScopedSetMainThreadBlocked mainThreadBlocked;
99 Proxy::implThread()->postTask(base::Bind(&ThreadProxy::requestReadbackOn ImplThread, base::Unretained(this), &request)); 97 Proxy::implThread()->postTask(base::Bind(&ThreadProxy::requestReadbackOn ImplThread, base::Unretained(this), &request));
100 request.completion.wait(); 98 request.completion.wait();
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 { 329 {
332 DCHECK(isImplThread()); 330 DCHECK(isImplThread());
333 TRACE_EVENT0("cc", "ThreadProxy::setNeedsCommitOnImplThread"); 331 TRACE_EVENT0("cc", "ThreadProxy::setNeedsCommitOnImplThread");
334 m_schedulerOnImplThread->setNeedsCommit(); 332 m_schedulerOnImplThread->setNeedsCommit();
335 } 333 }
336 334
337 void ThreadProxy::setNeedsForcedCommitOnImplThread() 335 void ThreadProxy::setNeedsForcedCommitOnImplThread()
338 { 336 {
339 DCHECK(isImplThread()); 337 DCHECK(isImplThread());
340 TRACE_EVENT0("cc", "ThreadProxy::setNeedsForcedCommitOnImplThread"); 338 TRACE_EVENT0("cc", "ThreadProxy::setNeedsForcedCommitOnImplThread");
341 m_schedulerOnImplThread->setNeedsCommit();
342 m_schedulerOnImplThread->setNeedsForcedCommit(); 339 m_schedulerOnImplThread->setNeedsForcedCommit();
343 } 340 }
344 341
345 void ThreadProxy::postAnimationEventsToMainThreadOnImplThread(scoped_ptr<Animati onEventsVector> events, base::Time wallClockTime) 342 void ThreadProxy::postAnimationEventsToMainThreadOnImplThread(scoped_ptr<Animati onEventsVector> events, base::Time wallClockTime)
346 { 343 {
347 DCHECK(isImplThread()); 344 DCHECK(isImplThread());
348 TRACE_EVENT0("cc", "ThreadProxy::postAnimationEventsToMainThreadOnImplThread "); 345 TRACE_EVENT0("cc", "ThreadProxy::postAnimationEventsToMainThreadOnImplThread ");
349 m_mainThreadProxy->postTask(FROM_HERE, base::Bind(&ThreadProxy::setAnimation Events, base::Unretained(this), base::Passed(events.Pass()), wallClockTime)); 346 m_mainThreadProxy->postTask(FROM_HERE, base::Bind(&ThreadProxy::setAnimation Events, base::Unretained(this), base::Passed(events.Pass()), wallClockTime));
350 } 347 }
351 348
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 { 394 {
398 DCHECK(isMainThread()); 395 DCHECK(isMainThread());
399 DCHECK_NE(m_deferCommits, deferCommits); 396 DCHECK_NE(m_deferCommits, deferCommits);
400 m_deferCommits = deferCommits; 397 m_deferCommits = deferCommits;
401 398
402 if (m_deferCommits) 399 if (m_deferCommits)
403 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::setDeferCommits", this); 400 TRACE_EVENT_ASYNC_BEGIN0("cc", "ThreadProxy::setDeferCommits", this);
404 else 401 else
405 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::setDeferCommits", this); 402 TRACE_EVENT_ASYNC_END0("cc", "ThreadProxy::setDeferCommits", this);
406 403
407 if (!m_deferCommits && m_deferredCommitPending) { 404 if (!m_deferCommits && m_pendingDeferredCommit)
408 m_deferredCommitPending = false; 405 m_mainThreadProxy->postTask(FROM_HERE, base::Bind(&ThreadProxy::beginFra me, base::Unretained(this), base::Passed(m_pendingDeferredCommit.Pass())));
409 m_mainThreadProxy->postTask(FROM_HERE, base::Bind(&ThreadProxy::beginFra me, base::Unretained(this)));
410 }
411 } 406 }
412 407
413 bool ThreadProxy::commitRequested() const 408 bool ThreadProxy::commitRequested() const
414 { 409 {
415 DCHECK(isMainThread()); 410 DCHECK(isMainThread());
416 return m_commitRequested; 411 return m_commitRequested;
417 } 412 }
418 413
419 void ThreadProxy::setNeedsRedrawOnImplThread() 414 void ThreadProxy::setNeedsRedrawOnImplThread()
420 { 415 {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 DCHECK(isImplThread()); 476 DCHECK(isImplThread());
482 m_layerTreeHostImpl->finishAllRendering(); 477 m_layerTreeHostImpl->finishAllRendering();
483 completion->signal(); 478 completion->signal();
484 } 479 }
485 480
486 void ThreadProxy::forceBeginFrameOnImplThread(CompletionEvent* completion) 481 void ThreadProxy::forceBeginFrameOnImplThread(CompletionEvent* completion)
487 { 482 {
488 TRACE_EVENT0("cc", "ThreadProxy::forceBeginFrameOnImplThread"); 483 TRACE_EVENT0("cc", "ThreadProxy::forceBeginFrameOnImplThread");
489 DCHECK(!m_beginFrameCompletionEventOnImplThread); 484 DCHECK(!m_beginFrameCompletionEventOnImplThread);
490 485
486 setNeedsForcedCommitOnImplThread();
491 if (m_schedulerOnImplThread->commitPending()) { 487 if (m_schedulerOnImplThread->commitPending()) {
492 completion->signal(); 488 completion->signal();
493 return; 489 return;
494 } 490 }
495 491
496 m_beginFrameCompletionEventOnImplThread = completion; 492 m_beginFrameCompletionEventOnImplThread = completion;
497 setNeedsForcedCommitOnImplThread();
498 } 493 }
499 494
500 void ThreadProxy::scheduledActionBeginFrame() 495 void ThreadProxy::scheduledActionBeginFrame()
501 { 496 {
502 TRACE_EVENT0("cc", "ThreadProxy::scheduledActionBeginFrame"); 497 TRACE_EVENT0("cc", "ThreadProxy::scheduledActionBeginFrame");
503 DCHECK(!m_pendingBeginFrameRequest); 498 scoped_ptr<BeginFrameAndCommitState> beginFrameState(new BeginFrameAndCommit State);
504 m_pendingBeginFrameRequest = make_scoped_ptr(new BeginFrameAndCommitState()) ; 499 beginFrameState->monotonicFrameBeginTime = base::TimeTicks::Now();
505 m_pendingBeginFrameRequest->monotonicFrameBeginTime = base::TimeTicks::Now() ; 500 beginFrameState->scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
506 m_pendingBeginFrameRequest->scrollInfo = m_layerTreeHostImpl->processScrollD eltas(); 501 beginFrameState->implTransform = m_layerTreeHostImpl->implTransform();
507 m_pendingBeginFrameRequest->implTransform = m_layerTreeHostImpl->implTransfo rm(); 502 beginFrameState->memoryAllocationLimitBytes = m_layerTreeHostImpl->memoryAll ocationLimitBytes();
enne (OOO) 2012/11/02 18:02:57 Maybe move the DCHECK(memoryAllocationLimitBytes)
508 m_pendingBeginFrameRequest->memoryAllocationLimitBytes = m_layerTreeHostImpl ->memoryAllocationLimitBytes();
509 if (m_layerTreeHost->contentsTextureManager()) 503 if (m_layerTreeHost->contentsTextureManager())
510 m_layerTreeHost->contentsTextureManager()->getEvictedBackings(m_pending BeginFrameRequest->evictedContentsTexturesBackings); 504 m_layerTreeHost->contentsTextureManager()->getEvictedBackings(beginFram eState->evictedContentsTexturesBackings);
511 505
512 m_mainThreadProxy->postTask(FROM_HERE, base::Bind(&ThreadProxy::beginFrame, base::Unretained(this))); 506 m_mainThreadProxy->postTask(FROM_HERE, base::Bind(&ThreadProxy::beginFrame, base::Unretained(this), base::Passed(beginFrameState.Pass())));
513 507
514 if (m_beginFrameCompletionEventOnImplThread) { 508 if (m_beginFrameCompletionEventOnImplThread) {
515 m_beginFrameCompletionEventOnImplThread->signal(); 509 m_beginFrameCompletionEventOnImplThread->signal();
516 m_beginFrameCompletionEventOnImplThread = 0; 510 m_beginFrameCompletionEventOnImplThread = 0;
517 } 511 }
518 } 512 }
519 513
520 void ThreadProxy::beginFrame() 514 void ThreadProxy::beginFrame(scoped_ptr<BeginFrameAndCommitState> beginFrameStat e)
521 { 515 {
522 TRACE_EVENT0("cc", "ThreadProxy::beginFrame"); 516 TRACE_EVENT0("cc", "ThreadProxy::beginFrame");
523 DCHECK(isMainThread()); 517 DCHECK(isMainThread());
524 if (!m_layerTreeHost) 518 if (!m_layerTreeHost)
525 return; 519 return;
526 520
527 if (m_deferCommits) { 521 if (m_deferCommits) {
528 m_deferredCommitPending = true; 522 m_pendingDeferredCommit = beginFrameState.Pass();
529 m_layerTreeHost->didDeferCommit(); 523 m_layerTreeHost->didDeferCommit();
530 TRACE_EVENT0("cc", "EarlyOut_DeferCommits"); 524 TRACE_EVENT0("cc", "EarlyOut_DeferCommits");
531 return; 525 return;
532 } 526 }
533 527
534 if (!m_pendingBeginFrameRequest) {
535 TRACE_EVENT0("cc", "EarlyOut_StaleBeginFrameMessage");
536 return;
537 }
538
539 if (m_layerTreeHost->needsSharedContext() && !WebSharedGraphicsContext3D::ha veCompositorThreadContext()) 528 if (m_layerTreeHost->needsSharedContext() && !WebSharedGraphicsContext3D::ha veCompositorThreadContext())
540 WebSharedGraphicsContext3D::createCompositorThreadContext(); 529 WebSharedGraphicsContext3D::createCompositorThreadContext();
541 530
542 scoped_ptr<BeginFrameAndCommitState> request(m_pendingBeginFrameRequest.Pass ());
543
544 // Do not notify the impl thread of commit requests that occur during 531 // Do not notify the impl thread of commit requests that occur during
545 // the apply/animate/layout part of the beginFrameAndCommit process since 532 // the apply/animate/layout part of the beginFrameAndCommit process since
546 // those commit requests will get painted immediately. Once we have done 533 // those commit requests will get painted immediately. Once we have done
547 // the paint, m_commitRequested will be set to false to allow new commit 534 // the paint, m_commitRequested will be set to false to allow new commit
548 // requests to be scheduled. 535 // requests to be scheduled.
549 m_commitRequested = true; 536 m_commitRequested = true;
550 m_commitRequestSentToImplThread = true; 537 m_commitRequestSentToImplThread = true;
551 538
552 // On the other hand, the animationRequested flag needs to be cleared 539 // On the other hand, the animationRequested flag needs to be cleared
553 // here so that any animation requests generated by the apply or animate 540 // here so that any animation requests generated by the apply or animate
554 // callbacks will trigger another frame. 541 // callbacks will trigger another frame.
555 m_animateRequested = false; 542 m_animateRequested = false;
556 543
557 // FIXME: technically, scroll deltas need to be applied for dropped commits as well. 544 if (beginFrameState) {
558 // Re-do the commit flow so that we don't send the scrollInfo on the BFAC me ssage. 545 m_layerTreeHost->applyScrollAndScale(*beginFrameState->scrollInfo);
559 m_layerTreeHost->applyScrollAndScale(*request->scrollInfo); 546 m_layerTreeHost->setImplTransform(beginFrameState->implTransform);
560 m_layerTreeHost->setImplTransform(request->implTransform); 547 }
561 548
562 if (!m_inCompositeAndReadback && !m_layerTreeHost->visible()) { 549 if (!m_inCompositeAndReadback && !m_layerTreeHost->visible()) {
563 m_commitRequested = false; 550 m_commitRequested = false;
564 m_commitRequestSentToImplThread = false; 551 m_commitRequestSentToImplThread = false;
565 m_forcedCommitRequested = false;
566 552
567 TRACE_EVENT0("cc", "EarlyOut_NotVisible"); 553 TRACE_EVENT0("cc", "EarlyOut_NotVisible");
568 Proxy::implThread()->postTask(base::Bind(&ThreadProxy::beginFrameAborted OnImplThread, base::Unretained(this))); 554 Proxy::implThread()->postTask(base::Bind(&ThreadProxy::beginFrameAborted OnImplThread, base::Unretained(this)));
569 return; 555 return;
570 } 556 }
571 557
572 m_layerTreeHost->willBeginFrame(); 558 m_layerTreeHost->willBeginFrame();
573 559
574 m_layerTreeHost->updateAnimations(request->monotonicFrameBeginTime); 560 base::TimeTicks frameBeginTime = beginFrameState ? beginFrameState->monotoni cFrameBeginTime : base::TimeTicks::Now();
enne (OOO) 2012/11/02 18:02:57 This looks a little problematic. When we get the
561 m_layerTreeHost->updateAnimations(frameBeginTime);
575 m_layerTreeHost->layout(); 562 m_layerTreeHost->layout();
576 563
577 // Clear the commit flag after updating animations and layout here --- objec ts that only 564 // Clear the commit flag after updating animations and layout here --- objec ts that only
578 // layout when painted will trigger another setNeedsCommit inside 565 // layout when painted will trigger another setNeedsCommit inside
579 // updateLayers. 566 // updateLayers.
580 m_commitRequested = false; 567 m_commitRequested = false;
581 m_commitRequestSentToImplThread = false; 568 m_commitRequestSentToImplThread = false;
582 m_forcedCommitRequested = false;
583 569
584 if (!m_layerTreeHost->initializeRendererIfNeeded()) { 570 if (!m_layerTreeHost->initializeRendererIfNeeded()) {
585 TRACE_EVENT0("cc", "EarlyOut_InitializeFailed"); 571 TRACE_EVENT0("cc", "EarlyOut_InitializeFailed");
586 return; 572 return;
587 } 573 }
588 574
589 m_layerTreeHost->contentsTextureManager()->unlinkEvictedBackings(request->ev ictedContentsTexturesBackings); 575 if (beginFrameState)
576 m_layerTreeHost->contentsTextureManager()->unlinkEvictedBackings(beginFr ameState->evictedContentsTexturesBackings);
590 577
591 scoped_ptr<ResourceUpdateQueue> queue = make_scoped_ptr(new ResourceUpdateQu eue); 578 scoped_ptr<ResourceUpdateQueue> queue = make_scoped_ptr(new ResourceUpdateQu eue);
592 m_layerTreeHost->updateLayers(*(queue.get()), request->memoryAllocationLimit Bytes); 579 m_layerTreeHost->updateLayers(*(queue.get()), beginFrameState ? beginFrameSt ate->memoryAllocationLimitBytes : 0);
593 580
594 // Once single buffered layers are committed, they cannot be modified until 581 // Once single buffered layers are committed, they cannot be modified until
595 // they are drawn by the impl thread. 582 // they are drawn by the impl thread.
596 m_texturesAcquired = false; 583 m_texturesAcquired = false;
597 584
598 m_layerTreeHost->willCommit(); 585 m_layerTreeHost->willCommit();
599 // Before applying scrolls and calling animate, we set m_animateRequested to 586 // Before applying scrolls and calling animate, we set m_animateRequested to
600 // false. If it is true now, it means setNeedAnimate was called again, but 587 // false. If it is true now, it means setNeedAnimate was called again, but
601 // during a state when m_commitRequestSentToImplThread = true. We need to 588 // during a state when m_commitRequestSentToImplThread = true. We need to
602 // force that call to happen again now so that the commit request is sent to 589 // force that call to happen again now so that the commit request is sent to
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 } 960 }
974 961
975 void ThreadProxy::renderingStatsOnImplThread(CompletionEvent* completion, Render ingStats* stats) 962 void ThreadProxy::renderingStatsOnImplThread(CompletionEvent* completion, Render ingStats* stats)
976 { 963 {
977 DCHECK(isImplThread()); 964 DCHECK(isImplThread());
978 m_layerTreeHostImpl->renderingStats(stats); 965 m_layerTreeHostImpl->renderingStats(stats);
979 completion->signal(); 966 completion->signal();
980 } 967 }
981 968
982 ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState() 969 ThreadProxy::BeginFrameAndCommitState::BeginFrameAndCommitState()
970 : memoryAllocationLimitBytes(0)
983 { 971 {
984 } 972 }
985 973
986 ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState() 974 ThreadProxy::BeginFrameAndCommitState::~BeginFrameAndCommitState()
987 { 975 {
988 } 976 }
989 977
990 } // namespace cc 978 } // namespace cc
OLDNEW
« cc/scheduler_state_machine.cc ('K') | « cc/thread_proxy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698